跳到正文
Elaine Blog
返回

线程生命周期、等待通知与中断协议

并发编程

Java 中断不是强制终止线程,而是协作式取消信号。任务代码必须决定在哪里检查信号、怎样清理资源,以及是否向上层传播。 本文先运行一个可取消工作线程,再解释 waitnotifyjoin 的边界。

Table of contents

Open Table of contents

运行中断实验

下载中断协议样例下载, 在并发实验室运行:

mvn package
java -cp target/classes dev.elaine.concurrency.InterruptionSample

输出应包含:

收到中断,开始清理
工作线程已结束=true

interrupt() 只设置中断状态;线程在 sleepwaitjoin 等可中断等待中会收到 InterruptedException。这些方法抛出 异常时会清除中断状态,因此示例在完成本层清理前调用 Thread.currentThread().interrupt() 恢复信号。

看懂六种线程状态

Thread.State 用六个枚举描述 Java 级状态:

状态含义常见来源
NEW尚未启动刚创建的线程
RUNNABLE可运行或正在执行计算、部分 I/O
BLOCKED等待进入监视器竞争 synchronized
WAITING无限期等待wait()join()park()
TIMED_WAITING有期限等待sleep()、带超时的等待
TERMINATED已结束run() 返回或抛出未捕获异常

RUNNABLE 不等于持续占用 CPU。线程转储中的 Java 状态需要结合多次采样、系统 CPU 和调用栈判断。

wait 与 notify 必须保护条件

wait() 会原子地释放当前对象监视器并等待;返回前会重新获得监视器。它可能被中断,也允许伪唤醒,所以必须在 while 中重新检查业务条件:

synchronized (queue) {
    while (queue.isEmpty()) {
        queue.wait();
    }
    return queue.removeFirst();
}

修改条件的一方也要持有同一监视器,再调用 notifyAll()。优先使用 BlockingQueueCountDownLatch 等高级工具;只有 实现底层同步结构或维护旧代码时才直接使用等待集。

join 等待的是线程结束

worker.join() 让当前线程等待 worker 终止。工作线程终止前的操作 happens-before join() 成功返回后的操作,因此 调用方能看到工作线程最终写入。但生产等待应有超时或上层取消策略,避免一个失联任务永久卡住关闭流程。

中断处理规则

下一步

阅读JMM、Happens-Before 与三类并发性质,理解中断标志和 任务结果为何能跨线程可见。


分享这篇文章:

上一篇
JDK 升级与 JVM 性能回归
下一篇
JMM、Happens-Before 与三类并发性质