Table of contents
-
- 1. Five states
- 2. Six states
-
- According to the Thread.State enumeration, it is divided into six states
- Verify state in Java
- Let’s analyze the transition of the six states of Java in different situations
-
-
- Case 1 `NEW --> RUNNABLE`
- Case 2 `RUNNABLE <--> WAITING`
- Case 3 `RUNNABLE <--> WAITING`
- Case 4 `RUNNABLE <--> WAITING`
- Case 5 `RUNNABLE <--> TIMED_WAITING`
- Case 6 `RUNNABLE <--> TIMED_WAITING`
- Case 7 `RUNNABLE <--> TIMED_WAITING`
- Case 8 `RUNNABLE <--> TIMED_WAITING`
- Case 9 `RUNNABLE <--> BLOCKED`
- Case 10 `RUNNABLE <--> TERMINATED`
-
1. Five states
This is described from the operating system level
- [Creation Status] The thread object is only created at the language level, and has not yet been associated with the operating system thread
- [Runnable state] (ready state) means that the thread has been created (associated with the operating system thread) and can be scheduled and executed by the CPU
- [Running status] refers to the status of obtaining the running status of the CPU time slice
- When the CPU time slice is used up, it will switch from [running state] to [runnable state], which will cause thread context switching
- 【Blocking state】
- If the blocking API is called, such as BIO reading and writing files, the thread will not actually use the CPU at this time, which will cause the thread context to switch and enter the [blocked state]
- After the BIO operation is completed, the operating system will wake up the blocked thread and switch to the [runnable state]
- The difference from [runnable state] is that for threads in [blocked state], as long as they do not wake up, the scheduler will never consider scheduling them
- 【Termination state】Indicates that the thread has been executed, the life cycle has ended, and it will not be converted to other states
State transition conditions:
- Ready state→Running state: After the process in the ready state is scheduled, it obtains processor resources (allocation of processor time slices), so the process changes from the ready state to the running state.
- Running state → ready state: The process in the running state has to give up the processor after the time slice is used up, so that the process is converted from the running state to the ready state. Furthermore, in a preemptible operating system, when a higher priority process becomes ready, the scheduler transitions the executing process to the ready state, allowing the higher priority process to execute.
- Running state → blocking state: When a process requests the use and allocation of a resource (such as a peripheral) or waits for an event to occur (such as the completion of an I/O operation), it transitions from the running state to the blocking state. The process requests the operating system to provide services in the form of system calls, which is a form of calling the operating system kernel process by running user mode programs.
- Blocking state → ready state: When the process is waiting for an event to arrive, such as the end of the I/O operation or the end of the interrupt, the interrupt handler must change the state of the corresponding process from the blocked state to the ready state.
2. Six states
This is described from the Java API level
According to the Thread.State enumeration, it is divided into six states
- The NEW thread has just been created, but the start() method has not been called yet
- RUNNABLE After calling the start() method, note that the RUNNABLE state at the Java API level covers the [runnable state], [running state] and [blocked state] at the operating system level (thread blocking due to BIO, in Java Indistinguishable, still considered runnable)
- BLOCKED , WAITING , TIMED_WAITING are all subdivisions of [blocking state] at the Java API level, which will be detailed in the state transition section later
- TERMINATED when the thread code finishes running
Thread.State is an internal enumeration class that defines 6 enumeration constants:
public enum State {
// 新建状态
NEW,
// 运行状态
RUNNABLE,
/**
* 阻塞状态
* Object.wait
*/
BLOCKED,
/**
* 等待状态
* Object.wait
* Thread.join
* LockSupport.park
*/
WAITING,
/**
* 限时等待状态
* Thread.sleep
* Object.wait
* Thread.join
* LockSupport.parkUntil
* LockSupport.parkNanos
*/
TIMED_WAITING,
// 终止状态
TERMINATED;
}
Verify state in Java
@Slf4j(topic = "c.threadState")
public class ThreadState {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.debug("running...");
}
};
Thread t2 = new Thread("t2") {
@Override
public void run() {
while(true) {
// runnable
}
}
};
t2.start();
Thread t3 = new Thread("t3") {
@Override
public void run() {
log.debug("running...");
}
};
t3.start();
Thread t4 = new Thread("t4") {
@Override
public void run() {
synchronized (ThreadState.class) {
try {
Thread.sleep(1000000); // timed_waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t4.start();
Thread t5 = new Thread("t5") {
@Override
public void run() {
try {
t2.join(); // waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t5.start();
Thread t6 = new Thread("t6") {
@Override
public void run() {
synchronized (ThreadState.class) {
// blocked
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t6.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("t1 state {}", t1.getState());
log.debug("t2 state {}", t2.getState());
log.debug("t3 state {}", t3.getState());
log.debug("t4 state {}", t4.getState());
log.debug("t5 state {}", t5.getState());
log.debug("t6 state {}", t6.getState());
System.in.read();
}
}
output:
17:46:11.509 [t3] DEBUG c.threadState - running...
17:46:12.008 [main] DEBUG c.threadState - t1 state NEW
17:46:12.016 [main] DEBUG c.threadState - t2 state RUNNABLE
17:46:12.017 [main] DEBUG c.threadState - t3 state TERMINATED
17:46:12.017 [main] DEBUG c.threadState - t4 state TIMED_WAITING
17:46:12.017 [main] DEBUG c.threadState - t5 state WAITING
17:46:12.017 [main] DEBUG c.threadState - t6 state BLOCKED
Let’s analyze the transition of the six states of Java in different situations
Suppose there are threads
Thread t
case 1NEW --> RUNNABLE
- When calling
t.start()
the method , by NEW --> RUNNABLE
case 2RUNNABLE <--> WAITING
After the t threadsynchronized(obj)
acquires the object lock with
obj.wait()
When the method is called , the t thread starts fromRUNNABLE --> WAITING
- call
obj.notify()
,obj.notifyAll()
whent.interrupt()
_- The contention lock is successful, and the t thread starts from
WAITING --> RUNNABLE
- Contended lock failure, t thread from
WAITING --> BLOCKED
- The contention lock is successful, and the t thread starts from
public class TestWaitNotify {
final static Object obj = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj) {
log.debug("执行....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...."); // 断点
}
},"t1").start();
new Thread(() -> {
synchronized (obj) {
log.debug("执行....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...."); // 断点
}
},"t2").start();
TimeUnit.MILLISECONDS.sleep(500);
log.debug("唤醒 obj 上其它线程");
synchronized (obj) {
obj.notifyAll(); // 唤醒obj上所有等待线程 断点
}
}
}
case 3RUNNABLE <--> WAITING
- When the current thread calls
t.join()
the method , the current thread starts fromRUNNABLE --> WAITING
Note that the current thread is waiting on the monitor of the t thread object - t When the thread finishes running, or calls interrupt() of the current thread , the current thread starts from
WAITING --> RUNNABLE
case 4RUNNABLE <--> WAITING
- Calling
LockSupport.park()
the method the current thread will cause the current thread toRUNNABLE --> WAITING
- Calling
LockSupport.unpark
(target thread) or calling threadinterrupt()
will make the target thread fromWAITING --> RUNNABLE
case 5RUNNABLE <--> TIMED_WAITING
After the t threadsynchronized(obj)
acquires the object lock with
obj.wait(long n)
When the method is called , the t thread starts fromRUNNABLE --> TIMED_WAITING
- t thread waits for more than n milliseconds, or when calling
obj.notify()
,obj.notifyAll()
,t.interrupt()
- The contention lock is successful, and the t thread starts from
TIMED_WAITING --> RUNNABLE
- Contended lock failure, t thread from
TIMED_WAITING --> BLOCKED
- The contention lock is successful, and the t thread starts from
Situation 6RUNNABLE <--> TIMED_WAITING
- When the current thread calls
t.join(long n)
the method , the current thread starts fromRUNNABLE --> TIMED_WAITING
Note that the current thread is waiting on the monitor of the t thread object - When the current thread waits for more than n milliseconds, or when the t thread finishes running, or calls the current thread's , the current thread starts from
interrupt()
TIMED_WAITING --> RUNNABLE
case 7RUNNABLE <--> TIMED_WAITING
- Called by the current thread
Thread.sleep(long n)
, the current thread starts fromRUNNABLE --> TIMED_WAITING
- The current thread wait time exceeds n milliseconds, the current thread from
TIMED_WAITING --> RUNNABLE
case 8RUNNABLE <--> TIMED_WAITING
- When the current thread calls
LockSupport.parkNanos(long nanos)
orLockSupport.parkUntil(long millis)
, the current thread starts fromRUNNABLE --> TIMED_WAITING
- Calling
LockSupport.unpark
(target thread) or calling threadinterrupt()
, or waiting for timeout , will make the target thread fromTIMED_WAITING--> RUNNABLE
Situation 9RUNNABLE <--> BLOCKED
- If the competition fails when the t thread
synchronized(obj)
acquires the object lock withRUNNABLE --> BLOCKED
- After the execution of the synchronization code block of the obj-locked thread is completed,
BLOCKED
all re-compete. If thread t succeeds in the competition,BLOCKED --> RUNNABLE
other failed threads will stillBLOCKED
Case 10RUNNABLE <--> TERMINATED
- After all the codes of the current thread have finished running, enter
TERMINATED