100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Java

Thread Lifecycle in Java

Understand the states a Java thread passes through — from NEW to TERMINATED — as defined by the Thread.State enum, and what causes each transition.

Multithreading & Advanced JavaIntermediate8 min readJul 7, 2026
Analogies

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

java
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()); // TERMINATED

3. 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

java
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

text
Before start: NEW
After start, during sleep: TIMED_WAITING
After join: TERMINATED

6. 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

Was this page helpful?

Topics covered

#Java#JavaProgrammingStudyNotes#Programming#ThreadLifecycleInJava#Thread#Lifecycle#Syntax#Explanation#Concurrency#StudyNotes#SkillVeris