Java is one of the most popular programming languages for building multi-threaded applications. Understanding the lifecycle and states of a thread in Java is crucial for writing efficient, concurrent programs. Threads allow a program to perform multiple tasks simultaneously, which is especially important for real-world applications like web servers, data processing, and GUI applications.
In this guide, we will explore the thread lifecycle in Java, different thread states, their transitions, practical examples, and best practices for beginners and intermediate learners.
A thread is the smallest unit of execution in a Java program. Java supports multithreading, which allows multiple threads to run concurrently. Each thread operates independently but shares the same memory space of the application.
Key benefits of using threads:
Every thread in Java goes through a lifecycle with different states. The Java Thread lifecycle is managed by the Java Virtual Machine (JVM) and consists of the following stages:
When a thread is created using either the Thread class or Runnable interface but not yet started, it is in the new state.
class MyThread extends Thread { public void run() { System.out.println("Thread is running..."); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); // Thread in New state System.out.println("Thread created: " + t1.getName()); } }
Explanation: The thread
t1 is created but not yet started. Calling t1.start() will move the thread from New to Runnable state.
A thread enters the Runnable state when
start() is called. It is ready to run, but it waits for CPU scheduling.
MyThread t1 = new MyThread(); t1.start(); // Thread now in Runnable state
Explanation: Runnable does not mean the thread is currently running; it is eligible for execution. The JVM thread scheduler decides when the thread will move to the Running state.
A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time, and the thread actively executes its task in this state.
class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }
Explanation:
A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time, and the thread actively executes its task in this state.
class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }
Explanation:
start() is called, the thread moves from Runnable to Running when the JVM thread scheduler picks it for execution.run() method contains the code that will execute while the thread is in the Running state.A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time.
class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }
A thread enters the Blocked state when it is waiting to acquire a lock on an object. Similarly, the Waiting state occurs when a thread waits indefinitely until another thread signals it.
class SharedResource { synchronized void display() { System.out.println(Thread.currentThread().getName() + " is accessing resource"); try { Thread.sleep(2000); } catch (InterruptedException e) { } } } public class ThreadExample { public static void main(String[] args) { SharedResource resource = new SharedResource(); Thread t1 = new Thread(() -> resource.display()); Thread t2 = new Thread(() -> resource.display()); t1.start(); t2.start(); // t2 may enter Blocked state } }
A thread enters Timed Waiting when it waits for a specific amount of time using methods like sleep(), join(timeout), or wait(timeout).
Thread t1 = new Thread(() -> { try { Thread.sleep(3000); // Timed Waiting System.out.println("Thread finished sleeping"); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start();
A thread enters the Terminated state once it completes execution or is stopped. Once dead, a thread cannot be restarted.
Thread t1 = new Thread(() -> System.out.println("Thread completed")); t1.start(); System.out.println("Is thread alive? " + t1.isAlive()); // false if terminated
| Thread State | Description | Example Method |
|---|---|---|
| New | Thread created but not started | new Thread() |
| Runnable | Thread ready to run, waiting for CPU | start() |
| Running | Thread executing its task | run() |
| Blocked/Waiting | Thread waiting for lock or signal | synchronized / wait() |
| Timed Waiting | Thread waiting for a specified time | sleep() / join(timeout) |
| Terminated (Dead) | Thread finished execution | N/A |
class FileDownloader extends Thread { String fileName; FileDownloader(String fileName) { this.fileName = fileName; } public void run() { System.out.println("Downloading: " + fileName); try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println("Downloaded: " + fileName); } } public class MultiDownload { public static void main(String[] args) { FileDownloader f1 = new FileDownloader("file1.pdf"); FileDownloader f2 = new FileDownloader("file2.pdf"); f1.start(); f2.start(); } }
Runnable: Thread is ready to run but waiting for CPU scheduling.
Running: Thread is actively executing its task.
No, a terminated thread cannot be restarted. You need to create a new thread object.
Thread t = new Thread(); System.out.println(t.getState());
Knowing the lifecycle helps in:
Understanding the lifecycle and states of a thread in Java is fundamental for building efficient and responsive applications. By mastering thread states like New, Runnable, Running, Waiting, Timed Waiting, and Terminated, developers can manage concurrency, improve performance, and prevent common pitfalls such as deadlocks or race conditions. Practical examples, from GUI apps to file downloads, demonstrate how threads can be applied in real-world scenarios. Following best practices ensures threads operate safely and efficiently in your Java applications.
Copyrights © 2024 letsupdateskills All rights reserved