What Are the Different Thread States in Java with Code Examples?
In Java, thread management is a critical concept for building efficient, high-performance applications. The java.lang.Thread
class provides built-in support for multithreading, and understanding the Thread lifecycle is essential to effectively utilize these capabilities.
Java threads can exist in the following states as defined in the Thread.State
enum:
- NEW
- RUNNABLE
- BLOCKED
- WAITING
- TIMED_WAITING
- TERMINATED
Let’s explore each state with detailed explanations and code examples to bring the concept to life.
1. NEW
A thread is in the NEW state when it is created but not yet started.
Thread t = new Thread(() -> {
System.out.println("Running thread");
});
System.out.println(t.getState()); // Output: NEW
Explanation: The thread object is instantiated, but start()
has not been invoked.
2. RUNNABLE
A thread is in the RUNNABLE state after the start()
method is called and before it enters the waiting or terminated states.
Thread t = new Thread(() -> {
while(true) {
// Simulating work
}
});
t.start();
System.out.println(t.getState()); // Might output: RUNNABLE
Explanation: The thread is ready to run and may be executing or waiting for CPU time.
3. BLOCKED
A thread is in the BLOCKED state when it tries to access a synchronized block or method locked by another thread.
class Shared {
synchronized void method() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
}
}
Shared obj = new Shared();
Thread t1 = new Thread(() -> obj.method());
Thread t2 = new Thread(() -> obj.method());
t1.start();
t2.start();
Thread.sleep(100); // Let t1 acquire the lock
System.out.println(t2.getState()); // BLOCKED
Explanation: t2
waits for the lock held by t1
.
4. WAITING
The WAITING state occurs when a thread waits indefinitely for another thread to perform a particular action.
Thread t = new Thread(() -> {
synchronized (Thread.currentThread()) {
try {
Thread.currentThread().wait();
} catch (InterruptedException e) {}
}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // WAITING
Explanation: The thread waits without a timeout, requiring notify()
or notifyAll()
to resume.
5. TIMED_WAITING
This state is like WAITING but with a timeout.
Thread t = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // TIMED_WAITING
Explanation: The thread will return to RUNNABLE after 5 seconds or if interrupted.
6. TERMINATED
A thread is in the TERMINATED state when it completes execution or is aborted.
Thread t = new Thread(() -> System.out.println("Done!"));
t.start();
t.join();
System.out.println(t.getState()); // TERMINATED
Explanation: The thread has finished its work and exited.
Visual Summary of Thread States
Here’s a quick visual of how threads transition:
- NEW → RUNNABLE
- RUNNABLE → WAITING / TIMED_WAITING / BLOCKED
- Any → TERMINATED when the run completes or an exception is thrown
Best Practices
- Always handle
InterruptedException
properly inWAITING
andTIMED_WAITING
states. - Avoid busy waiting; use proper synchronization constructs.
- Understand thread states to debug deadlocks and performance issues.
Conclusion
Understanding thread states in Java is crucial for mastering concurrency. From the creation of a thread to its termination, Java provides a rich and well-structured model to handle thread lifecycle. Mastery of these concepts ensures better performance and fewer bugs in concurrent applications.
By understanding the transitions between NEW
, RUNNABLE
, BLOCKED
, WAITING
, TIMED_WAITING
, and TERMINATED
, you can design more efficient and maintainable Java applications.