1. Thread state
In Java, the state of a thread is described by an enumeration type.This enumeration has six values: NEW (new), RUNNABLE (running), BLOCKED (lock pool), TIMED_WAITING (timed waiting), WAITING (waiting), TERMINATED (terminating, ending).
However, most people understand the above six differently, usually adding blocking state, runnable state, suspended state.
Six thread states are given in the enumeration java.lang.Thread.State in the API.
This is the source code for the Thread class's enumerated class that describes the state of the thread:
public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
2. Most people's understanding of thread state and state transition
Threads are always in one of five states from creation, run, to end: new, ready, running, blocked, and dead.
Thread state transition diagram:
2.1 New Status
When a thread is created with the new operator, such as new Thread(r), the thread has not yet started running, and the thread is in a new state.When a thread is in a new state, the program has not yet started running the code in the thread.
2.2 Ready State
A newly created thread does not start automatically. To execute a thread, the thread's start () method must be called.When the thread object calls the start () method, the thread is started, the start () method creates system resources for the thread to run, and dispatches the thread to run() the method.When the start() method returns, the thread is ready.
Threads in a ready state do not necessarily run the run() method immediately. Threads must also compete with other threads for CPU time. Threads can only run if they get CPU time.Because in a single CPU computer system, it is not possible to run multiple threads at the same time, only one thread is running at a time.So there may be multiple threads ready at this point.For multiple threads in a ready state, the
The thread scheduler of the Java runtime system to schedule.
2.3 Running State
When a thread gets CPU time, it enters the running state and actually starts executing the run() method.
2.4 Blocking State
Threads may be blocked for various reasons while running:
- Threads go to sleep by calling the sleep method;
2. A thread invokes an operation that is blocked on I/O, that is, the operation will not return to its caller until the input and output operations are completed;
3. The thread is trying to get a lock that is being held by another thread;
4. Threads are waiting for a trigger condition;
2.5 Mortality
Thread death occurs for two reasons:
1. The run method exited normally and died naturally.
- An uncaught exception terminated the run method and caused the thread to die suddenly.
To determine if a thread is currently alive (either running or blocked), you need to use the isAlive method.This method returns true if it is runnable or blocked; false if the thread is still new and not runnable, or if the thread is dead.3. Additional understanding of thread state and state transition
According to official source code, a thread has six states, no blocking state, no runnable state, no pending state.The conditions under which each thread state occurs are listed here, and each state is explained in detail below:
Thread state | Conditions leading to state change |
---|---|
NEW (New) | The thread was just created, but it was not started.The start() method has not been called yet. |
Runnable | The state in which a thread can run in a java virtual machine, either running its own code or not, depending on the operating system processor. |
Blocked | When a thread attempts to acquire an object lock that is held by another thread, the thread enters the Blocked state; when the thread holds a lock, the thread becomes the Runnable state. |
Waiting (unlimited waiting) | A thread enters the Waiting state while waiting for another thread to perform an action (wake up).You cannot wake up automatically after entering this state. You must wait for another thread to call the notify or notifyAll method to wake up. |
Timed Waiting | As with the waiting state, several methods have timeout parameters that call them and they will enter the TimedWaiting state.This status will remain until the timeout expires or a wake-up notification is received.Common methods with timeout parameters are Thread.sleep, Object.wait. |
Teminated (Terminated) | Either died because the run method exited normally or because an exception that was not caught terminated the run method. |
We don't need to study how these states are implemented, we just need to know that they exist in threading operations.So how do we understand these states? New and terminated are easy to understand. Let's look at the transition of threads from Runnable to non-runnable.
3.1 TimedWaiting
A timed wait state (TIMED_WAITING) occurs when a thread calls the sleep() method or when another thread in the current thread calls the join() method with a time parameter.
Code example:
/** * @author bruceliu * @create 2019-06-01 22:35 * @description TimedWaiting(Timing Wait) */ public class Test1 { public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread2 t2 = new Thread2(); t1.setThread2(t2); t1.start(); t2.start(); } } //Thread1 is responsible for printing the status of both threads. class Thread1 extends Thread { private Thread2 t2; public void setThread2(Thread2 t2) { this.t2 = t2; } @Override public void run() { System.out.println("Get into t1 thread"); for (int i = 0; i < 5; i++) { try { System.out.println("t1 Status of: " + getState()); System.out.println("t2 Status of: " + t2.getState()); System.out.println(); //To reduce the number of prints, t1 sleeps 1 second per print Thread.sleep(1000); } catch (InterruptedException e) { } } } } class Thread2 extends Thread { @Override public void run() { System.out.println("Get into t2 Threads, go to sleep immediately"); try { //Sleep for 5 seconds. sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t2 End of Sleep"); } }
The case study shows that the sleep method is still simple to use.We need to remember the following points:
- A common scenario to enter the TIMED_WAITING state is to invoke the sleep method, which can also be invoked by a separate thread, without necessarily having a collaborative relationship.
- To give other threads the opportunity to execute, you can place the call to Thread.sleep() within the thread run().This ensures that the thread will sleep during execution
- Sleep is not related to locks. Threads wake up automatically when sleep expires and return to the Runnable state.
The time specified in sleep() is the shortest time a thread will not run.Therefore, the sleep() method does not guarantee that the thread will start executing immediately after its sleep expires.
Timed Waiting Thread Status Diagram:
3.2 BLOCKED (Lock Blocked)
The Blocked state is described in the API as being the state of a thread that is blocking waiting for a monitor lock (lock object).
This is a very understandable state if we have already learned the synchronization mechanism.For example, thread A uses the same lock as thread B code. If thread A acquires the lock and thread A enters the Runnable state, then thread B enters the Blocked state.
This is from the Runnable state to the Blocked state.In addition to this, the Waiting and Time Waiting states can also be blocked under certain circumstances, and this section serves as an expanded point of knowledge to take you through.
Blocked Thread Status Diagram:
3.3 Waiting (unlimited waiting)
The Wating state is described in the API as the state of a thread that is waiting indefinitely for another thread to perform a particular (wake-up) action.So have we experienced this before?The answer is no, but it doesn't prevent us from having a simple, in-depth understanding.Let's learn through a code:
package com.bruceliu.demo7; /** * @author bruceliu * @create 2019-05-30 16:59 * @description */ public class WaitingTest { public static Object obj = new Object(); public static void main(String[] args) { // Demonstrate waiting new Thread(new Runnable() { @Override public void run() { while (true) { synchronized (obj) { try { System.out.println(Thread.currentThread().getName() + "=== from waiting Wake up, get the lock object, continue execution"); obj.wait(); //Wait infinitely //obj.wait(5000); //timer wait, 5 seconds to wake up automatically } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "=== from waiting Wake up, get the lock object, continue execution"); } } } }, "Waiting Threads").start(); new Thread(new Runnable() { @Override public void run() { while (true) { //Wake up every 3 seconds try { System.out.println(Thread.currentThread().getName() + "‐‐‐‐‐ Wait 3 seconds"); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj) { System.out.println(Thread.currentThread().getName() + "‐‐‐‐‐ Get Lock Object,call notify Method to release the lock object"); obj.notify(); } } } }, "Wake Threads").start(); } }
In the above case, we find that a thread that calls the Object.wait method of an object waits for another thread to call the Object.notify() or Object.notifyAll() method of that object.In fact, the waiting state is not the operation of a single thread, it reflects the communication between multiple threads, which can be understood as the collaborative relationship between multiple threads. Multiple threads will strive for locks, while there is a collaborative relationship between them.Like you and your colleagues in the company, you may be competing for promotions, but more often you work together to accomplish certain tasks.When multiple threads collaborate, such as A and B threads, if A thread calls the wait() method in the Runnable state, A thread enters the Waiting state and loses the synchronization lock.If at this point the B thread acquires a synchronization lock and calls the notify() method in its running state, it will wake up an infinitely waiting A thread.Note that if a lock object is acquired, thread A wakes up and enters the Runnable state; if no lock object is acquired, it enters the Blocked state.
Waiting Thread Status Diagram:
3.4 Summary
So far, we have a basic understanding of thread state. For more information, see the following figure:
When we look through the API, we will find that Timed Waiting is closely related to Waiting state, such as the wait method in Waiting state is empty parameter, while the wait method in timed waiting state is parameterized.This method with parameters is actually a countdown operation, which is equivalent to the small alarm clock in our life. We set the time to notify when it is due, but if we get the (wake up) notification in advance, setting the time for the notification would seem like a waste of effort, so this design actually kills two birds with one stone.If no (wake up) notification is received, the thread is in the Timed Waiting state until the countdown finishes automatically waking up; if a (wake up) notification is received during the countdown, the thread wakes up immediately from the Timed Waiting state.