Thread States in Java


🚀 Thread States in Java: Deep Dive into Multithreading

Multithreading is a vital concept in Java programming that enables concurrent execution of two or more parts of a program. Java provides extensive support for multithreading through the java.lang.Thread class and associated utilities. A critical concept to grasp while working with threads is Thread States.

Understanding thread states is essential for diagnosing performance bottlenecks, deadlocks, and designing responsive applications. This post will provide an in-depth look at the various Thread States in Java, how they transition, and practical examples to bring clarity.


🔎 What Are Thread States?

Thread states in Java define the different phases a thread can go through during its life cycle. Java 5 introduced the java.lang.Thread.State enum which captures these states. Each thread transitions through these states based on its execution and synchronization behavior.

The States are:

  1. NEW

  2. RUNNABLE

  3. BLOCKED

  4. WAITING

  5. TIMED_WAITING

  6. TERMINATED

Let’s break down each state.


1. 📅 NEW

  • This is the state of a thread when it has been created but not yet started.

  • The thread is simply an object of the Thread class, and no system resources have been allocated to it.

Thread t = new Thread(() -> System.out.println("Running"));
// t is in NEW state

2. 🎉 RUNNABLE

  • After the start() method is called, the thread moves to the RUNNABLE state.

  • The thread is considered to be executing in the Java Virtual Machine but may not actually be running on the CPU.

  • The Thread Scheduler manages the execution and decides when the thread will get CPU time.

t.start(); // t is now in RUNNABLE state

Note: A thread in the RUNNABLE state could either be running or ready to run, depending on CPU availability.


3. ❌ BLOCKED

  • A thread enters the BLOCKED state when it attempts to access an object monitor that is already held by another thread.

  • This occurs when threads use synchronized blocks or methods to access shared resources.

synchronized (object) {
    // only one thread can execute here at a time
}
  • If another thread is already inside the synchronized block, other threads trying to enter will be BLOCKED until the lock is released.


4. ⏳ WAITING

  • A thread enters the WAITING state when it waits indefinitely for another thread to perform a specific action.

  • It must be explicitly notified to come out of this state.

Common Methods Causing WAITING State:

  • Object.wait()

  • Thread.join() (without a timeout)

  • LockSupport.park()

synchronized (object) {
    object.wait(); // thread goes to WAITING state
}

Important: A thread in WAITING does not resume on its own. Another thread must call notify() or notifyAll().


5. ⏰ TIMED_WAITING

  • A thread enters the TIMED_WAITING state when it waits for a specific amount of time.

  • After the time expires, it transitions back to RUNNABLE.

Methods That Cause TIMED_WAITING:

  • Thread.sleep(milliseconds)

  • Object.wait(milliseconds)

  • Thread.join(milliseconds)

  • LockSupport.parkNanos() / parkUntil()

Thread.sleep(1000); // thread is in TIMED_WAITING for 1 second

6. ☠️ TERMINATED

  • A thread enters the TERMINATED state (also known as DEAD) when it has completed its execution or has been terminated due to an exception.

  • Once terminated, a thread cannot be restarted.

System.out.println("Thread execution finished"); // thread is TERMINATED

If you try to call start() on a thread that has already been terminated, you'll get IllegalThreadStateException.


💡 Transition Diagram

         +---------+
         |  NEW    |
         +---------+
              |
              | start()
              v
         +----------+        preempted       +---------+
         | RUNNABLE |<---------------------->| RUNNING |
         +----------+                        +---------+
              |                                  |
              |                                  | completes/run ends
              |                                  v
         +-------------+                  +-----------+
         | BLOCKED     |<----lock-------- | TERMINATED|
         +-------------+                  +-----------+
              ^
              |
      +---------------+<-----notify()------+
      |    WAITING    |                    |
      +---------------+     timeout()      |
              ^                        +---------------+
              +--------wait(timeout)-->| TIMED_WAITING |
                                       +---------------+

📚 Practical Insights

Monitoring Thread States

Use tools like:

  • jconsole

  • VisualVM

  • Java Flight Recorder

  • Thread dumps

These tools help visualize thread behavior and detect issues like deadlocks, thread starvation, and bottlenecks.

Deadlock Example

Two threads waiting on each other's locks can lead to a deadlock:

Thread 1: Locks A, waits for B
Thread 2: Locks B, waits for A

Both threads end up in the BLOCKED state indefinitely.


🤔 Final Thoughts

Understanding thread states gives you a deeper control over your Java programs. It equips you to debug multithreaded applications effectively, prevent concurrency issues, and build responsive and reliable systems.

As you build more complex applications, knowing exactly what state a thread is in can be the difference between smooth performance and system meltdown.

Previous
Next Post »