Java Thread States: Overview of the Six Lifecycle States
This article explains Java's six thread states—NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, and TERMINATED—detailing their meanings, transitions, related waiting and synchronization queues, and comparing key thread-control methods such as sleep, yield, join, wait, and notify.
Java defines six thread states that describe a thread's lifecycle.
1. NEW : A thread object has been created but start() has not been called. 2. RUNNABLE : The thread is ready to run or is currently running; after start() the thread is placed in the runnable pool awaiting CPU time. 3. BLOCKED : The thread is blocked while trying to acquire a lock. 4. WAITING : The thread is waiting indefinitely for another thread to perform a specific action (notify or interrupt). 5. TIMED_WAITING : Similar to WAITING but the thread will automatically return after a specified timeout. 6. TERMINATED : The thread has completed execution.
Thread State Diagram
1. Initial State
Implementing the Runnable interface or extending Thread and creating an instance puts the thread into the NEW state.
2.1. Runnable (Ready) State
The thread is eligible to run but has not yet been selected by the scheduler.
Calling start() moves the thread to the ready state.
When sleep() ends, join() ends, or after user input, the thread becomes ready.
When the thread's time slice expires and yield() is called, it returns to the ready state.
After acquiring the object lock from the lock pool, the thread becomes ready.
2.2. Running State
The scheduler selects a thread from the runnable pool to execute; this is the only way a thread enters the running state.
3. Blocked State
A thread is blocked when it attempts to enter a synchronized method or block and cannot acquire the lock.
4. Waiting State
The thread does not receive CPU time and must be explicitly awakened; otherwise it remains in indefinite waiting.
5. Timed Waiting State
The thread does not receive CPU time but will automatically wake after a specified timeout.
6. Terminated State
The thread ends when its run() method or the main() method completes; it cannot be restarted.
Calling start() on a terminated thread throws java.lang.IllegalThreadStateException.
Waiting Queue
Before calling obj.wait() or obj.notify(), the thread must hold the object's lock (i.e., be inside a synchronized(obj) block).
Related steps and diagram are shown.
1. Thread 1 acquires lock on object A and uses it.
2. Thread 1 calls A.wait().
3. Thread 1 releases the lock and enters the waiting queue.
4. Other threads compete for A's lock.
5. Thread 5 acquires A's lock, enters the synchronized block, and uses A.
6. Thread 5 calls A.notifyAll(), waking all waiting threads; if notify() is used, only one thread is awakened arbitrarily and moves to the synchronization queue.
7. After notifyAll()'s synchronized block ends, Thread 5 releases A's lock.
8. Threads in the synchronization queue compete for the lock; the exact timing of when Thread 1 reacquires it is nondeterministic.
Synchronization Queue State
When a thread attempts to call a synchronized method on object A but the lock is held, it enters the synchronization queue, which holds threads waiting for the lock.
If a thread is awakened by another thread, it moves to the synchronization queue to compete for the lock.
The synchronization queue exists per object in a synchronized context.
Comparison of Several Methods
Thread.sleep(long millis) : The current thread sleeps, entering TIMED_WAITING without releasing the lock; after the timeout it becomes ready. Useful for giving other threads execution opportunities.
Thread.yield() : The current thread voluntarily yields its CPU time slice without releasing the lock, moving back to the ready state; it does not guarantee other threads will run.
t.join() / t.join(long millis) : The current thread waits for thread t to finish (or timeout), entering WAITING/TIMED_WAITING without releasing its lock; once t completes or timeout expires, it becomes ready.
obj.wait() : The current thread releases the object's lock and enters the waiting queue, to be awakened by notify/notifyAll or a timeout.
obj.notify() / obj.notifyAll() : Wake one or all threads waiting on the object's monitor; the choice of which thread to wake is arbitrary.
Question
When many threads are waiting on an object's wait() and one thread calls notify(), which thread is awakened? The Java documentation states the choice is arbitrary and implementation‑dependent.
If you find this sharing useful, feel free to like and share.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.