In this section, we will learn what a thread life cycle is and how it works in Java.
Threads states in Java
From the moment we create a thread to the time that the work of the thread is done, a thread goes through multiple states, which we know it as the life cycle of a thread.
In short, the states of a thread are:
- New
- Runnable
- Blocked
- Waiting
- Timed-waiting
- Terminated
Note that these are states that the JVM assigns to a thread! They don’t represent the states that an OS sets for threads.
Java Thread State: New
The first state of a thread is called new. A thread goes to this state when we create it for the very first time (For example, by creating an object from the Thread class).
Note that a thread is in the New state until we call the start() method on that thread! From the moment of calling the `start()` method onward, the thread is no-longer in the New state.
How to get the state of a Thread? (Java Thread getState() Method)
We can get the state of a thread using the getState() method. Simply call this method on the target thread and it will return a value of type State which is an enum. Now we can send this value to the output stream, for example, to see the state of the target thread.
Example: getting the state of a thread in Java
public class Main { public volatile static boolean run = true; public static void main(String[] args) { Main main = new Main(); Thread t1 = new Thread(Main::run, "Thread-one"); System.out.println("The state of the t1 thread before calling the start() method: "+ t1.getState()); t1.start(); System.out.println("The state of the t1 thread after calling the start() method: "+ t1.getState()); try { Thread.sleep(3000); main.stop(); Thread.sleep(1000); System.out.println("The state of the t1 thread after terminating the thread: "+ t1.getState()); } catch (InterruptedException e) { e.printStackTrace(); } } private static void run() { System.out.println("Thread is running..."); while(run){ try { System.out.println("Thread went to sleep"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Thread stopped..."); } public void stop(){ Main.run = false; } }
Output:
The state of the t1 thread before calling the start() method: NEW The state of the t1 thread after calling the start() method: RUNNABLE Thread is running... Thread went to sleep Thread went to sleep Thread went to sleep Thread stopped... The state of the t1 thread after terminating the thread: TERMINATED
Java Thread State: Runnable
A thread that is ready to run or running is in the Runnable state! Note that from the OS perspective, a thread goes into two states relative to its running states! These two states are:
- Ready to Run: A thread that is ready to run but is waiting for its turn to get the CPU’s time is in the state of `Ready to Run`.
- Running: A thread that is currently taking the CPU’s time and running its instructions, we call the state of that thread as Running.
But be aware that JVM put these two states together and calls it Runnable state.
Java Thread State: Blocked
A thread is in the blocked state if it tries to enter or reenter a synchronized block or method, but was blocked because another thread currently acquired the lock.
Note: please check the Java synchronization section if you’re not familiar with the synchronization.
Example: putting a thread into blocked state
public class Main { public static Thread t1; public static Thread t2; public static void main(String[] args) { Main main = new Main(); t1 = new Thread(main::run, "Thread-one"); t2 = new Thread(main::run, "Thread-two"); t1.start(); t2.start(); } public synchronized void run() { System.out.println("The thread that acquired the lock is: "+Thread.currentThread().getName()); if (t1.getState() == Thread.State.BLOCKED){ System.out.println("The state of the thread one is: "+t1.getState()); }else if(t2.getState() == Thread.State.BLOCKED){ System.out.println("The state of the thread two is: "+ t2.getState()); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }
Output:
The thread that acquired the lock is: Thread-one The state of the thread two is: BLOCKED The thread that acquired the lock is: Thread-two
In this example, the first thread got the access to the `run()` method and so the second thread is blocked at this time. For this reason, when we called the `getState()` method on the second thread, we got the `BLOCKED` state.
Java Thread State: Waiting
A thread may go into the waiting state, if it calls one of the following methods:
- wait(): this method belongs to the Object class and a thread may call this method if it wants to wait for a condition to hold true. Note that a thread can only call this method if it acquired the lock of the target object. (Meaning the thread was running a synchronized method/block). We will explain the wait() method in the next section.
- `join()`: Using this method, we can cause a thread to wait until another thread (the one that this method is called with) finishes its work. We will explain the join() method in later sections.
Java Thread State: Timed-Waiting
The timed-waiting state happens when a thread goes into the waiting state but for a specific period of time!
This is done by calling a version of the wait() method that takes a time argument as well. Now, when a thread runs the wait() method with a time value, that thread goes into the waiting state but for a period that we set as the argument of the method. After the declared time elapsed, the state of the target thread will change and it becomes Runnable.
Java Thread State: Terminated
When the work of a thread is done (For example, after running all the instructions in its run() method), that thread will terminate and its state becomes Terminated (Meaning the thread is basically dead now).
Example: terminating a thread
public class Main { public volatile static boolean run = true; public static void main(String[] args) { Main main = new Main(); Thread t1 = new Thread(Main::run, "Thread-one"); System.out.println("The state of the t1 thread before calling the start() method: "+ t1.getState()); t1.start(); System.out.println("The state of the t1 thread after calling the start() method: "+ t1.getState()); try { Thread.sleep(3000); main.stop(); Thread.sleep(1000); System.out.println("The state of the t1 thread after terminating the thread: "+ t1.getState()); } catch (InterruptedException e) { e.printStackTrace(); } } private static void run() { System.out.println("Thread is running..."); while(run){ try { System.out.println("Thread went to sleep"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Thread Terminated..."); } public void stop(){ Main.run = false; } }
Output:
The state of the t1 thread before calling the start() method: NEW The state of the t1 thread after calling the start() method: RUNNABLE Thread is running... Thread went to sleep Thread went to sleep Thread went to sleep Thread Terminated... The state of the t1 thread after terminating the thread: TERMINATED
As you can see from the last statement on the output, the state of the `t1` thread turned into `TERMINATED` after that the thread finished executing the instructions of the `run()` method.
Java Thread stop() Method:
Another way of terminating a thread is by calling the stop() method on that thread.
After calling this method, it will terminate the target thread immediately.
Note that the method does not take an argument, and also it will not return a value.
Example: calling the Thread stop() method to stop a thread in Java
public class Main { public static void main(String[] args) { Thread t1 = new Thread(Main::run, "Thread-one"); t1.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("The state of the t1 thread is: "+t1.getState()); } private static void run() { System.out.println("Thread is running..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Thread.currentThread().stop(); System.out.println("Thread Terminated..."); } }
Output:
Thread is running... The state of the t1 thread is: TERMINATED
In this example, note that the `run()` method has another statement after the call to the `stop()` method. But because by calling the `stop()` method, the target thread will terminate immediately, the last statement after this stop() method got skipped.