Java’s multithreading capability allows developers to create applications that can handle multiple tasks simultaneously, making them more responsive and efficient. To effectively manage threads, understanding Java’s thread states and lifecycle is crucial. This guide provides a comprehensive look at the five primary states a Java thread can exist in — New, Runnable, Blocked, Waiting, and Terminated — along with practical examples, transitions, and best practices for managing thread states effectively.


Introduction to Java Thread States

A thread in Java goes through a specific lifecycle with several states, each representing a stage in its execution journey. The main states include:

  1. New: The thread has been created but not yet started.
  2. Runnable: The thread is ready to execute and is waiting for CPU allocation.
  3. Blocked: The thread is trying to access a locked resource and is waiting to acquire it.
  4. Waiting: The thread is waiting indefinitely for another thread’s action.
  5. Terminated: The thread has completed its execution.

Let’s explore each state in detail, along with transitions and practical examples to clarify their roles in thread management.


1. The New State

The New state is the initial state of a thread. When an instance of the Thread class is created, the thread is in the New state but hasn’t been started yet. This state is similar to an unlaunched rocket — it’s initialized but hasn’t taken off.

Example of Thread in New State

Java
public class NewStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("Thread is created but not yet started"));
        // Thread is currently in the New state
    }
}

In the example, the thread is created, but it hasn’t started yet and will stay in the New state until the start() method is called.

Transition: Calling start() on a thread in the New state will transition it to the Runnable state.


2. The Runnable State

A thread in the Runnable state is ready to execute but may not be running yet due to CPU scheduling. When the thread gets CPU time, it enters the running state within the Runnable state. However, the JVM decides which thread will actually execute based on factors like priority and resource availability.

Example of Runnable State

Java
public class RunnableStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("Thread is now running"));
        thread.start(); // Transitions to Runnable state
    }
}

Transition: A thread in the Runnable state may move back and forth between being actively running and waiting for CPU time as managed by the thread scheduler.


3. The Blocked State

A thread enters the Blocked state when it’s trying to enter a synchronized block or method but can’t due to another thread holding the lock. The Blocked state is temporary; once the lock is available, the thread will move back to the Runnable state.

Example of Blocked State

Java
public class BlockedStateExample {
    private static final Object LOCK = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(BlockedStateExample::syncMethod);
        Thread thread2 = new Thread(BlockedStateExample::syncMethod);

        thread1.start();
        thread2.start();
    }

    public static void syncMethod() {
        synchronized (LOCK) {
            System.out.println("Thread " + Thread.currentThread().getName() + " is in the method");
            try {
                Thread.sleep(2000); // Simulate processing
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

In this example, if thread1 enters the syncMethod, thread2 will enter the Blocked state until thread1 releases the lock on LOCK.


4. The Waiting State

A thread is in the Waiting state when it’s waiting indefinitely for another thread’s action. This state is typically entered by calling methods like wait(), join(), or LockSupport.park(). The thread will only leave the Waiting state if it’s notified or interrupted.

Example of Waiting State

Java
public class WaitingStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("Child thread execution completed");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        thread.start();

        try {
            thread.join(); // Main thread enters Waiting state until child thread finishes
            System.out.println("Main thread resumed");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

Here, the main thread enters the Waiting state using join() until the child thread completes its execution.


5. The Timed Waiting State

A thread enters Timed Waiting when it’s waiting for a specific period. Methods like sleep(long millis), wait(long timeout), or join(long timeout) can put threads in this state. Once the waiting time elapses, the thread goes back to the Runnable state.

Example of Timed Waiting State

Java
public class TimedWaitingStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(3000); // Timed Waiting for 3 seconds
                System.out.println("Thread resumed after timed wait");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        thread.start();
    }
}

Explanation: The thread is in the Timed Waiting state for 3 seconds, then returns to Runnable.


6. The Terminated State

A thread enters the Terminated state once it has finished execution. After reaching this state, the thread cannot be restarted.

Example of Terminated State

Java
public class TerminatedStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> System.out.println("Thread is running"));
        thread.start();

        try {
            thread.join(); // Ensures thread completes
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Thread has terminated");
    }
}

FAQ Section on Java Thread States

  1. What are the main thread states in Java?
    Java thread states include New, Runnable, Blocked, Waiting, Timed Waiting, and Terminated.
  2. How does a thread move from New to Runnable?
    A thread moves from New to Runnable when the start() method is called.
  3. What causes a thread to enter the Blocked state?
    A thread enters Blocked if it’s trying to access a locked resource held by another thread.
  4. Can a thread be restarted after termination?
    No, once a thread is Terminated, it cannot be restarted.
  5. How do threads go from Waiting to Runnable?
    Threads in the Waiting state move to Runnable when notified or interrupted.
  6. What’s the difference between Waiting and Timed Waiting?
    Waiting is indefinite, while Timed Waiting has a specified duration.
  7. What is join() used for?
    join() makes the current thread wait until another thread completes.
  8. Can threads freely move between Runnable and Blocked?
    Yes, threads can move between these states based on resource availability.
  9. What happens if start() is called multiple times on a thread?
    Calling start() more than once throws an IllegalThreadStateException.
  10. Why is understanding thread states important?
    Understanding thread states helps manage concurrency, avoid deadlocks, and optimize performance.

Additional Resources

To further explore thread states in Java, check out these resources:


By understanding and managing Java thread states, developers can create efficient, scalable, and responsive applications. Knowledge of thread states is essential for avoiding concurrency issues and maximizing resource utilization in multithreaded Java applications.