Java线程状态详解
一、Java线程状态变迁(图片源自《Java 并发编程艺术》):
二、Java线程状态定义
特别注意每个状态上面注释,说明了哪些方法可以进入当前状态。
- NEW:调用
new Thread()
后进入该状态; - RUNNABLE:调用
Thread.start()
进入该状态;其它方式详见上面图示。 - BLOCKED:进入
synchronized
,等待获取锁时,进入该状态; - WAITING:调用
Object.wait()
、Thread.join
、LockSupport.park
后进入该状态; - TIMED_WAITING:调用
Object.wait(timeout)
、Thread.join(timeout)
、Thread.sleep
、LockSupport.parkNanos
、LockSupport.parkUntil
后进入该状态; - TERMINATED:
run()
方法执行完毕,进入该状态。
/**
* from java.lang.Thread.State
*
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*/
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
* Object.wait
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* “Object.wait” with no timeout
* “Thread.join” with no timeout
* “LockSupport.park”
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called “Object.wait()”
* on an object is waiting for another thread to call
* “Object.notify()” or “Object.notifyAll()” on
* that object. A thread that has called “Thread.join()”
* 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:
* “Thread.sleep”
* “Object.wait” with timeout
* “Thread.join” with timeout
* “LockSupport.parkNanos”
* “LockSupport.parkUntil”
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
三、代码实测
3.1 代码
public class ThreadStatus {
public static void main(String[] args) {
// 1.0 启动线程1
final LockSupportThread lockSupportThread = new LockSupportThread();
lockSupportThread.setName("ThreadStatus-lockSupportThread");
lockSupportThread.start();
// 2.0 启动线程2
final SynchronizedSleepThread synchronizedSleepThread = new SynchronizedSleepThread();
synchronizedSleepThread.setName("ThreadStatus-synchronizedSleepThread");
synchronizedSleepThread.start();
// 4.0 启动线程3、线程4
final ReentrantLock reentrantLock = new ReentrantLock();
final ReenterLockThread reenterLockSleepThread = new ReenterLockThread(reentrantLock);
reenterLockSleepThread.setName("ThreadStatus-reenterLockSleepThread");
reenterLockSleepThread.start();
final ReenterLockThread reenterLockWaitThread = new ReenterLockThread(reentrantLock);
reenterLockWaitThread.setName("ThreadStatus-reenterLockWaitThread");
reenterLockWaitThread.start();
}
static class ReenterLockThread extends Thread{
private Lock lock;
public ReenterLockThread(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.lock();
try {
try {
TimeUnit.HOURS.sleep(1);
} catch (InterruptedException e) {
System.out.println("interrupt");
}
} finally {
lock.unlock();
}
}
}
static class LockSupportThread extends Thread{
@Override
public void run() {
LockSupport.park(); // 线程进入 waiting 状态
}
}
static class SynchronizedSleepThread extends Thread{
@Override
public void run() {
final Object lock = new Object();
synchronized (lock) {
// 3.0 启动线程3
final SynchronizedBlockedThread synchronizedBlockedThread = new SynchronizedBlockedThread(lock);
synchronizedBlockedThread.setName("ThreadStatus-synchronizedBlockedThread");
synchronizedBlockedThread.start();
try {
TimeUnit.HOURS.sleep(1); // 线程继续持有锁,进入Timed_Waiting状态。
} catch (InterruptedException e) {
System.out.println("interrupt");
}
}
}
}
static class SynchronizedBlockedThread extends Thread{
private Object lock;
public SynchronizedBlockedThread(Object lock) {
this.lock = lock ;
}
@Override
public void run() {
synchronized (lock) { // 等待获取锁,线程进入Blocked状态。
System.out.println("enter synchronized block");
}
}
}
}
3.2 运行上面代码后在控制台通过jps
查看进程ID,然后用jstack 进程ID
来获取线程快照。
3.3、线程快照中找到我们代码中的3个线程状态,与我们在代码中注释一致,即:
LockSupport.park(); // 线程进入 waiting 状态
TimeUnit.HOURS.sleep(1); // 线程继续持有锁,进入Timed_Waiting状态
synchronized (lock) { // 等待获取锁,线程进入Blocked状态
特别注意:
- 阻塞在
java.concurrent
包中Lock
接口的线程状态是等待状态,因为java.concurrent
包中Lock
接口对于阻塞的实现均使用了LockSupport
类中的相关方法,即:LockSupport.park()
会使线程进入WAITING
状态; synchronized
等待获取锁时会进入BLOCKED
状态。
`tip:`
tid: java内的线程id
nid: 操作系统级别线程的线程id
prio: java内定义的线程的优先级
os_prio:操作系统级别的优先级
四、补充
4.1、jdk源码注释中有如下内容:
4.1.1 Java线程状态
和操作系统
中线程状态并非完全一致。
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
4.1.2 附:操作系统线程状态
- New: A process that has just been created but has not yet been admitted(承认) to the pool of executable processes by the operating system.
- Ready: A process that is prepared(准备) to execute when given the opportunity.
- Running: The process that is currently being executed.
- Waitting[Blocked]: A process that cannot execute until some event occurs(发生), such as the completion(完成) of an I/O operation.
- Terminated: A process that has been released from the pool of executable processes by the operating system,
either because it halted(停止) or because it aborted for some reason.
+----------<-----------+
| interrupt |
+-----------+ +-----------+ +---------------+ +------------+
| new |---------> | ready | | running |------->| terminated |
| | admitted | | | | exit | |
+-----------+ +-----------+ +---------------+ +------------+
| | scheduler patch | |
| +---------->-----------+ |
IO/ event completion | | IO / event waitting
| |
| +-------------+ |
+--<----| waitting |----<----+
| |
+-------------+
4.2、Java线程状态中 RUNNABLE
有如下注释:
操作系统中等待资源(例如CPU)的线程状态对于JVM
来说,线程都是RUNNABLE
* 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.
4.3、使用 Java 阻塞 I/O 模型读取数据,将会导致线程阻塞,线程将会进入休眠,从而让出 CPU 的执行权,直到数据读取完成。这个期间如果使用 jstack
查看线程状态,却可以发现 Java 线程状态
是处于 RUNNABLE
,这就和上面说的存在矛盾,为什么会这样?
当线程调用阻塞式 API,线程进入休眠状态,这里指的是操作系统层面的。从 JVM
层面,Java 线程状态依然处于RUNNABLE
状态。JVM
并不关心操作系统线程实际状态。从 JVM
看来等待 CPU
使用权(操作系统线程状态为可运行状态)与等待 I/O (操作系统线程状态处于休眠状态)没有区别,都是在等待某种资源,所以都归入 RUNNABLE
状态。