线程的状态
本文的主题是讨论线程的状态。主要为操作系统层面的线程状态以及JVM层面上的线程状态之间的联系。并对JVM线程不同状态间的转换的方式进行梳理。
1. 操作系统层面
操作系统层面的线程状态有五种,分别是:New、Ready、Running、Waiting、Terminate。如下图所示:

- New: 仅是在语⾔层⾯创建了线程对象,还未与操作系统线程关联;
- Ready: 指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执⾏;
- Running: 指获取了 CPU 时间⽚运⾏中的状态。当 CPU 时间⽚⽤完,会从运⾏状态转换⾄可运⾏状态,会导致线程的上下⽂切换;
- Waiting: 如果调⽤了阻塞 API,如 BIO 读写⽂件,这时该线程实际不会⽤到 CPU,会导致线程上下⽂切换,进⼊Waiting状态,等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换⾄Ready状态,与Ready的区别是,对Waiting的线程来说只要它们⼀直不唤醒,调度器就⼀直不会考虑调度它们。
- Terminate: 表示线程已经执行完毕,生命周期已经结束,不会转换为其他状态。
2. JVM层面
JVM层面的线程状态有六种,可以在java.lang.Thread.State源码中看到,分别是:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。如下:
1 | public enum State { |
3. 两种层面上线程状态的联系
以下为操作系统层面和JVM层面线程状态之间的关系:

忽略New和Terminate状态。由上图可见,JVM层面的Runnable状态包含了操作系统层面的 Ready、Running和Waiting状态。且BLOCKED、TIMED_WAITING、WAITING是JAVA层面对于 WAITING状态的细分。
Waiting状态在JVM层面也可以被认为是RUNNABLE是因为BIO导致的线程阻塞,Java无法区分。
4. 线程状态的转换
状态转换如下图所示:

对于各种状态转换的情况,以下将逐一解释其转换方式:
4.1 NEW –> RUNNABLE
- t.start()
4.2 RUNNABLE –> TERMINATE
当前线程的所有代码运行结束后,进入TERMINATE。
4.3 RUNNABLE <–> BLOCKED
- 线程用
synchronized(obj)获取对象锁时,若竞争失败,则进入BLOCKED; - 持对象锁线程的同步代码块执⾏完毕,会唤醒该对象上所有 BLOCKED 的线程重新竞争,如果其中 t 线程竞争 成功,从BLOCKED转为RUNNABLE ,其它失败的线程仍然 BLOCKED。
4.4 RUNNABLE <–> WAITING
- 当前线程调用
LockSupport.park()时,当前线程会进入WAITING状态。调用LockSupport.unpark()、interrupt()目标线程会进入RUNNABLE状态; - 当前线程调用
t.join()时,当前线程会进入WAITING状态。t线程运行结束或者调用t.interrupt()目标线程会进入RUNNABLE状态; - 当前线程调用
obj.wait()时,当前线程会进入WAITING状态。调用obj.notify()或者obj.notifyAll()时,目标线程有可能会进入RUNNABLE状态。
调用
notify()时,会随机唤醒一个线程,调用notifyAll()时,会唤醒此条件下的所有线程,让他们进行争抢锁资源,若没争抢到,则继续进入WAITING状态。否则,进入RUNNABLE状态。
4.5 RUNNABLE <–> TIMED_WAITING
- 当前线程调用
LockSupport.parkUtil()或者LockSupport.parkNanos()时,当前线程会进入TIMED_WAITING状态。调用LockSupport.unpark()或interrupt()目标线程会进入RUNNABLE状态; - 当前线程调用
t.join(long n)时,当前线程会进入TIMED_WAITING状态。当前线程等待了n毫秒或者t线程运行结束,或者调用了interrupt()时,当前线程会进入RUNNABLE状态; - 当前线程调用
wait(long n)时,当前线程会进入TIMED_WAITING状态。当前线程等待了n毫秒,当前线程会进入RUNNABLE状态。或者调用了notify()或notifyAll()时,当前线程有可能会进入RUNNABLE状态; - 当前线程调用
Thread.sleep(long n)时,当前线程会进入TIMED_WAITING状态。n毫秒后当前线程会进入RUNNABLE状态;
以上描述图示如下:

All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.