Java 线程生命周期:一种合法的示例顺序
84 秒,无声,中文字幕。A 为青绿,B 为琥珀色;中央显示对象 m 的 monitor owner。
所有画面只表示一种合法顺序,不承诺或预测 JVM 的调度。
[00:00:00.000 – 00:00:03.500] Java 线程有六种状态;任一时刻,一个线程只处于其中一种。
[00:00:03.500 – 00:00:07.000] 下面跟随线程 A、B 和对象 m,观察一种合法的执行顺序。
[00:00:07.000 – 00:00:11.000] 创建线程后是 NEW。调用 start(),线程进入 RUNNABLE。
[00:00:11.000 – 00:00:15.000] RUNNABLE 不等于一直占用 CPU;等待处理器也可能是这个状态。
[00:00:15.000 – 00:00:19.000] 本例 A 先获得 m 的 monitor,进入 synchronized(m)。
[00:00:19.000 – 00:00:23.000] B 尝试获取同一个 monitor,但 A 尚未释放,B 进入 BLOCKED。
[00:00:23.000 – 00:00:27.000] A 在同步块里调用 sleep(),进入 TIMED_WAITING。
[00:00:27.000 – 00:00:31.000] sleep() 不释放 monitor,所以 owner 仍是 A,B 仍然 BLOCKED。
[00:00:31.000 – 00:00:35.000] 睡眠结束后,A 继续执行;条件不满足,于是在循环内调用 m.wait()。
[00:00:35.000 – 00:00:38.000] A 进入 WAITING,并释放 m 的 monitor。本例 B 随后获得它。
[00:00:38.000 – 00:00:41.000] wait() 只释放 m 的 monitor,不会释放 A 持有的其他对象的锁。
[00:00:41.000 – 00:00:45.000] B 将条件 ready 设为 true,然后调用 m.notify(),本例唤醒 A。
[00:00:45.000 – 00:00:50.000] notify() 不释放锁。A 离开等待集,但仍因重新获取 monitor 而 BLOCKED。
[00:00:50.000 – 00:00:54.000] B 退出同步块,释放 monitor。本例 A 随后重新获得它。
[00:00:54.000 – 00:00:59.000] wait() 返回后,A 必须在 while 循环中重新检查条件,防止虚假唤醒等情况。
[00:00:59.000 – 00:01:05.000] 条件满足,A 完成工作、退出同步块并结束 run(),进入 TERMINATED。
[00:01:05.000 – 00:01:10.000] 另一个线程向 B 发送 interrupt()。本例 B 仍是 RUNNABLE,只是中断标志被设置。
[00:01:10.000 – 00:01:17.000] B 的代码主动检查中断标志,完成清理并退出 run(),随后才进入 TERMINATED。
[00:01:17.000 – 00:01:24.000] 中断不会自动终止线程。实际调度顺序可能不同,要分别观察线程状态和锁的 owner。
技术补充
1. BLOCKED 特指等待 monitor 锁,不泛指所有形式的阻塞。
2. wait/notify 都须在拥有对应对象 monitor 时调用。wait 只释放对应对象的 monitor。
3. notify 唤醒等待集中的一个线程,选择不确定;本示例只有 A 在等待。被通知线程须再次竞争 monitor,无优先拿锁保证。
4. wait 必须置于条件循环中。本例 B 在持有 m 时写 ready;A 重新获得同一 monitor 后检查 ready。
5. sleep、带正数超时的 wait/join 等可对应 TIMED_WAITING;无超时的 wait/join 和 park 等可对应 WAITING。视频不展开所有状态转换。
6. interrupt 的具体效果依赖线程正在做什么。示例 B 在同步块外运行,通过 isInterrupted() 检查标志并协作式退出。wait/sleep/join 也可能通过 InterruptedException 响应,抛出该异常时中断状态被清除。
7. run 正常返回或异常结束均可能导致线程终止;本例展示正常结束。
权威来源(核对日期:2026-10-08)
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Thread.State.html
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Thread.html#sleep(long)
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Thread.html#interrupt()
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Object.html#wait(long,int)
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Object.html#notify()