前言
梳理早期与 Thread 状态相关的笔记。
状态分类
通过查看 Thread 源码,我们可以看到在其类内部定义了线程的状态枚举:
1 | public class Thread implements Runnable { |
Thread 线程大致分为 6 种,即 NEW,RUNNABLE,BLOCKED, WAITING,TIMED_WAITING,TERMINATED。
其中:
- NEW: 新建状态(尚未启动的线程状态),即刚 new 出来,还没执行
start()
方法。 - RUNNABLE:可运行状态,可以细分两种 READY(就绪状态,调用了
start()
方法,等待获取 CPU 资源运行)和 RUNNING(运行状态,已获取到 CPU 资源)。 - BLOCKED:阻塞状态,等待拿到监视器锁/对象锁进入到同步方法或同步代码块。
- WAITING:等待状态
- TIMED_WAITING:超时等待状态
- TERMINATED:终止状态
状态转换
- 当线程被
new
出来时,处在 NEW 状态 - NEW 状态的线程调用
start()
方法后会变成 READY 状态。 - READY 状态的线程拿到 CPU 资源就可以执行任务,此时状态变为 RUNNING。
- RUNNING 状态中的线程会随着遇到不同情况,状态发生不同的变化:
① 线程成功执行完方法或中途遇到异常,状态会变为 TERMINATED。
② 线程在进到同步方法或同步代码块前,如果没有获取到监视器锁/对象锁,那么状态就会变为 BLOCKED。
③ 线程在运行过程中调用了 Object 的 wait()、Thread 的 join()、LockSupport.park() 方法后,状态会变成 WAITING。
④ 线程在运行过程中调用了 Object 的 wait(time)、Thread 的 sleep(time)、LockSupport.parkNanos(time)、LockSupport.parkUntil(time) 方法后,状态会变成 TIMED_WAITING。
- 处在 BLOCKED 状态的线程会被放到同步队列中。当持有锁的线程释放锁后会唤醒同步队列的线程,此时同步队列中的线程状态会变为 READY 竞争对象锁,如果竞争成功状态变为 RUNNING。竞争失败则状态再次变回 BLOCKED,被放回同步队列重复操作。
- 处在 WAITING 状态的线程会被放到等待队列中。当其他线程调用
notify()
、notifyAll()
、unpark(thread)
会唤醒等待队列的线程,此时等待队列中的线程状态会变为 READY 去竞争对象锁,如果竞争成功状态变为 RUNNING,从wait()
方法中返回。竞争失败则状态变成 BLOCKED,被放进同步队列。 - 处在 TIMED_WAITING 状态的线程会被放到等待队列中。有两种情况会唤醒等待队列中的该状态的线程,一种是手动调用
notify()
、notifyAll()
、unpark(thread)
方法,另一种是等待时间过后由 JVM 会自动调用notifyAll()
方法唤醒,然后执行上边描述的操作。