What are the thread states in Java and how does a thread… — Cracked Java
// Concurrency & Multithreading · Thread Fundamentals & Lifecycle
JuniorTheoryEPAM

What are the thread states in Java and how does a thread move between them?

A Java thread is always in exactly one of six states defined by the Thread.State enum: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, and TERMINATED. You query the current one with thread.getState().

The six states

  • NEW — created but start() not yet called.
  • RUNNABLE — eligible to run; either running on a core or waiting for the scheduler. Java does not distinguish "running" from "ready to run" — both are RUNNABLE. A thread blocked in an OS-level read (e.g. socket I/O) also shows as RUNNABLE.
  • BLOCKED — waiting to acquire a monitor lock to enter or re-enter a synchronized block. Only contention on intrinsic locks produces this state.
  • WAITING — parked indefinitely via Object.wait(), Thread.join(), or LockSupport.park(), until another thread signals it.
  • TIMED_WAITING — like WAITING but with a deadline: sleep(ms), wait(ms), join(ms), LockSupport.parkNanos.
  • TERMINATEDrun() has returned or thrown.

How a thread moves between them

NEW
| start()
v
RUNNABLE  <-------------------------------+
| synchronized (lock held by other)     | lock acquired
v                                        |
BLOCKED -----------------------------------+
| wait()/join()/park()        notify()/notifyAll()/unpark()/join target ends
v                                        |
WAITING -----------------------------------+
| sleep(t)/wait(t)/join(t)              timeout elapses
v                                        |
TIMED_WAITING -----------------------------+
|
| run() returns or throws
v
TERMINATED
Transitions and their triggers
Object lock = new Object();
Thread t = new Thread(() -> {
    synchronized (lock) {
        try { lock.wait(); } catch (InterruptedException e) {}
    }
});
System.out.println(t.getState());  // NEW
t.start();
Thread.sleep(50);
System.out.println(t.getState());  // WAITING (parked in wait())

Common confusion

BLOCKED is specifically about intrinsic-lock contention. A thread waiting on a ReentrantLock shows as WAITING (it uses LockSupport.park under AQS), not BLOCKED. And a thread doing blocking I/O is RUNNABLE, which surprises people reading thread dumps.

Mark your status