Threads play a crucial role in concurrent programming in Java, allowing developers to execute multiple tasks simultaneously. Understanding the life cycle of thread in Java is essential for efficient thread management and synchronization. In this article, we will delve into the different stages of thread life cycle in Java, exploring their characteristics and the methods associated with each stage.
Different States in the Life Cycle of Thread in Java
In Java, a thread goes through various states during its life cycle. The different states in the life cycle of thread in Java are:
New State
The life cycle of a thread begins in the “new” state, where a thread object is created but not yet started. At this stage, the thread is not executing any code. Key methods used in this stage include the Thread
class constructor and any initialization required before the thread’s execution.
Runnable State(Ready to Run)
Once the start()
method is called on a thread object, it enters the “runnable” state. In this state, the thread is ready to be executed, but the operating system scheduler has not yet selected it for execution. The scheduler determines the order in which threads are executed based on various factors such as thread priority. Methods such as start()
and run()
are relevant in this stage.
Running State
When the scheduler selects a thread from the runnable state, it enters the “running” state. The thread’s code is executed, and it actively performs its tasks. While in the running state, the thread may be paused or suspended due to factors like time slicing or thread priority changes.
Non Runnable State
This is the state when the thread is still alive, but is currently not eligible to run.A thread can enter in this state because of waiting the resources that are hold by another thread.
A thread becomes “Not Runnable” when one of these events occurs:
- If sleep method is invoked.
- The thread calls the wait method and now is waiting for notification.
- The thread is blocked for I/O.
- The thread is notified and is blocked for object lock acquisition.
- The thread is blocked for join completion.It waits for the other thread to finish execution.
Non Runnable State in turn can be of two types:
- Blocked/Waiting State
- Timed Waiting State
Blocked/Waiting State
Threads can enter the “blocked/waiting” state for various reasons. For example, if a thread is waiting for a resource or synchronization lock, it will be blocked until the resource becomes available or the lock is released. Common methods associated with this state include wait()
, notify()
, and notifyAll()
.
Timed Waiting State
Similar to the blocked/waiting state, a thread can also enter the “timed waiting” state. This state occurs when a thread waits for a specific period. Methods like sleep()
and join()
can put a thread into a timed waiting state.
Terminated State
The final stage in a thread’s life cycle is the “terminated” state. A thread reaches this state when its execution completes, either by reaching the end of its run()
method or by explicitly calling the stop()
method (which is deprecated and generally discouraged due to potential thread safety issues). Once terminated, a thread cannot be started again.
Java Code Depicting Different States of a Thread
Here’s a Java code sample that demonstrates the different thread states in the life cycle of thread in Java.
public class ThreadStatesExample {
public static void main(String[] args) throws InterruptedException {
// Create a new thread
Thread thread = new Thread(() -> {
System.out.println("Thread is running.");
try {
Thread.sleep(2000); // Sleep for 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("Thread State: " + thread.getState()); // Output: NEW
// Start the thread
thread.start();
System.out.println("Thread State: " + thread.getState()); // Output: RUNNABLE
Thread.sleep(100); // Sleep for a short duration
System.out.println("Thread State: " + thread.getState()); // Output: TIMED_WAITING
Thread.sleep(2000); // Sleep for 2 seconds to let the thread finish execution
System.out.println("Thread State: " + thread.getState()); // Output: TERMINATED
}
}
Output
Thread State: NEW
Thread State: RUNNABLE
Thread State: TIMED_WAITING
Thread State: TERMINATED
- The code begins by creating a new thread object and printing its initial state, which is “NEW”.
- The thread is started using the
start()
method, and its state transitions to “RUNNABLE”. The thread is now eligible for execution by the scheduler. - After a short sleep of 100 milliseconds, the main thread retrieves and prints the state of the thread, which has entered a “TIMED_WAITING” state. This occurs because the thread sleeps for 2 seconds (as defined in the
sleep()
method). - Finally, after the thread finishes executing its
run()
method and completes its task, the main thread checks and prints the state of the thread, which is now in the “TERMINATED” state.
Conclusion
Having a clear understanding of the life cycle of thread empowers developers to design robust and reliable concurrent systems. It helps them identify potential issues such as deadlocks, race conditions, and thread starvation, enabling effective troubleshooting and mitigation strategies.