线程的生命周期和状态
状态名称 | 说明 |
---|---|
New | 新创建 |
Runnable | 可运行 |
Blocked | 被阻塞 |
Waiting | 等待 |
Timed_waiting | 计时等待 |
Terminated | 被终止 |
-
New 表示线程被创建但尚未启动的状态
当我们用 new Thread() 新建一个线程时,如果线程没有开始运行 start() 方法,所以也没有开始执行 run() 方法里面的代码,那么此时它的状态就是 New ,而一旦线程调用了 start() 它的状态就会从 New 变成 Runnable -
Runnable 可运行
Java 中的 Runable 状态对应操作系统线程状态中的两种状态,分别是 Running 和 Ready
Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行正在等待被分配 CPU 资源 -
阻塞状态
- Blocked(被阻塞)
- 从 Runnable 状态进入 Blocked 状态只有一种可能,就是进入 synchronized 保护的代码时没有抢到 monitor 锁 无论是进入 synchronized 代码块 还是 synchronized 方法,都是一样
- 从 Blocked 状态进入 Runnable 状态 要求线程获取 monitor 锁
- Waiting(等待)
- 线程进入 Waiting 状态有三种可能性:
- 没有设置 Timeout 参数的 Object.wait() 方法
- 没有设置 Timeout 参数的 Thread.join() 方法
- LockSupport.park() 方法
- 从 Waiting 状态流转到其他状态则比较特殊
如果其他线程调用 notify() 或 notifyAll()来唤醒它它会直接进入 Blocked 状态 因为唤醒 Waiting 线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该 monitor 锁,所以处于 Waiting 状态的线程被唤醒时拿不 到该锁,就会进入 Blocked 状态
- 线程进入 Waiting 状态有三种可能性:
- Timed Waiting(计时等待)
- 线程进入 Timed Waiting 状态有四种可能性:
- 设置了时间参数的 Thread.sleep(long millis) 方 法
- 设置了时间参数的 Object.wait(long timeout) 方 法
- 设置了时间参数的 Thread.join(long millis) 方 法
- 设置了时间参数的 LockSupport.parkNanos(long nanos) 方法和LockSupport.parkUntil(long deadline) 方法
- Timed Waiting 中执行 notify() 和 notifyAll() 也是一样的道理
- 如果其他线程调用 notify() 或 notifyAll()来唤 醒它它会直接进入 Blocked 状态
- 如果它的超时时间到了且能直接获取到锁/join的线程运行结束/被中断/调用了LockSupport.unpark(),会直接恢复到 Runnable 状态,而无需经历 Blocked 状态
- 线程进入 Timed Waiting 状态有四种可能性:
- Terminated 终止
- 进入Terminated 终止状态有两种可能:
- run() 方法执行完毕,线程正常退出
- 出现一个没有捕获的异常,终止了 run() 方法,最终导致意外终止
- 进入Terminated 终止状态有两种可能:
- Blocked(被阻塞)
注意点
- 线程的状态是需要按照箭头方向来走的,比如线程从 New 状态是不可以直接进入 Blocked 状态的,它需要先经历 Runnable 状态
- 线程生命周期不可逆:一旦进入 Runnable 状态就不能回到 New 状态;一旦被终止就不可能 再有任何状态的变化。所以一个线程只能有一次 New 和 Terminated 状态,只有处于中间状 态才可以相互转换
wait/notify和sleep的异同
- 相同点:
- 它们都可以让线程阻塞
- 它们都可以响应 interrupt 中断,在等待的过程中如果收到中断信号,都可以进行响应, 并抛出 InterruptedException 异常
- 不同点:
- wait 方法必须在 synchronized 保护的代码中使用,而 sleep 方法并没有这个要求
- 在同步代码中执行 sleep 方法时,并不会释放 monitor 锁,但执行 wait 方法时会主动 释放 monitor 锁
- sleep 方法中会要求必须定义一个时间,时间到期后会主动恢复,而对于没有参数的 wait 方法而言,意味着永久等待,直到被中断或被唤醒才能恢复,它并不会主动恢复
- wait/notify 是 Object 类的方法,而 sleep 是 Thread 类的方法
网友评论