1. Introduction
Every thread in Java moves through a well-defined set of states during its lifetime, from the moment it is created to the moment it finishes execution. The JVM exposes these states directly through the nested enum java.lang.Thread.State, and understanding the transitions between them is essential for debugging concurrency issues such as deadlocks and threads stuck waiting.
Cricket analogy: Just as a match scorer tracks a bowler's status through overs — warming up, bowling, resting — the JVM exposes Thread.State to track every thread's status, crucial for spotting a batsman "stuck at the crease" deadlock.
Unlike a conceptual 'RUNNING' state used in some textbooks, the actual Thread.State enum defined by the JVM has exactly six values: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, and TERMINATED. You can query a thread's current state at any time using thread.getState().
Cricket analogy: Unlike a casual fan who just says a bowler is "bowling," the official scorecard has precise categories like NEW and RUNNABLE; calling thread.getState() is like checking the umpire's exact ruling instead of guessing.
2. Syntax
Thread t = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE (or TIMED_WAITING if already sleeping)
t.join();
System.out.println(t.getState()); // TERMINATED3. Explanation
NEW: a thread object has been created (e.g. new Thread(...)) but start() has not yet been called; no OS-level thread exists yet. RUNNABLE: after start() is called, the thread becomes RUNNABLE, meaning it is eligible to run and is either actually executing on a CPU core or waiting for the OS scheduler to give it CPU time — Java does not distinguish 'ready' from 'actually running' at the API level, both map to RUNNABLE.
Cricket analogy: NEW is like a batsman padded up in the dressing room before being announced; RUNNABLE is once they walk out — whether actually facing a ball or waiting at the non-striker's end, both count as "in play."
BLOCKED: a thread enters this state when it is waiting to acquire an intrinsic (synchronized) lock that another thread currently holds. WAITING: a thread enters this state when it calls Object.wait() (no timeout), Thread.join() (no timeout), or LockSupport.park(), and it will remain there until another thread notifies it, joins complete, or it is unparked. TIMED_WAITING: similar to WAITING but with a timeout, entered via Thread.sleep(millis), wait(timeout), join(timeout), or similar timed calls. TERMINATED: the thread has completed execution, either normally by returning from run() or abnormally due to an uncaught exception; a terminated thread cannot be restarted.
Cricket analogy: BLOCKED is a batsman waiting for the previous partner's wicket review to clear before facing; WAITING is waiting indefinitely for the next over's field change; TIMED_WAITING is waiting out a rain-delay clock; TERMINATED is when the innings ends, win or all-out.
Exam trap: There is no 'RUNNING' value in Thread.State — RUNNABLE covers both 'ready to run' and 'currently running'. Also, once a thread reaches TERMINATED it is permanently dead; calling start() again on it throws IllegalThreadStateException rather than restarting it.
4. Example
public class ThreadLifecycleDemo {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread worker = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(500); // TIMED_WAITING while holding the lock
} catch (InterruptedException ignored) { }
}
});
System.out.println("Before start: " + worker.getState()); // NEW
worker.start();
Thread.sleep(100); // give the worker time to start and sleep
System.out.println("After start, during sleep: " + worker.getState()); // TIMED_WAITING
worker.join();
System.out.println("After join: " + worker.getState()); // TERMINATED
}
}5. Output
Before start: NEW
After start, during sleep: TIMED_WAITING
After join: TERMINATED6. Key Takeaways
- Thread.State has exactly six values: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
- NEW means the Thread object exists but start() has not been called.
- RUNNABLE covers both 'ready to run' and 'currently executing' — there is no separate RUNNING state.
- BLOCKED means waiting to acquire a synchronized lock held by another thread.
- WAITING and TIMED_WAITING occur via wait()/join()/park(), with TIMED_WAITING having a timeout.
- TERMINATED is final — a terminated thread cannot be restarted with start().
Practice what you learned
1. Which of these is NOT an actual value of the Thread.State enum?
2. A thread calls Thread.sleep(2000). What state does it enter?
3. What state is a thread in if it is waiting to acquire a synchronized lock held by another thread?
4. What happens if you call start() on a thread that is already TERMINATED?
5. Which state is a thread in immediately after `new Thread(task)` is created but before start() is called?
Was this page helpful?
You May Also Like
Multithreading in Java
Learn how Java creates and runs multiple threads concurrently using the Thread class and Runnable interface, and why start() and run() behave so differently.
Synchronization in Java
Learn how the synchronized keyword prevents race conditions in Java by using intrinsic locks on objects and classes, and how deadlocks can arise.
Exceptions in Java
Understand what exceptions are in Java, how the Throwable hierarchy is organized, and why exception handling keeps programs robust.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics