Java中断是协作式通知而非强制终止,依赖线程主动检查isInterrupted()并响应;阻塞方法抛InterruptedException且清标志,需捕获后立即恢复;循环中须持续轮询中断状态并及时清理退出。

Java 的 interrupt() 不是“按下开关就断电”,而是发一条“请尽快收工”的协作通知。线程是否停、何时停、怎么停,全靠自己检查并响应。处理不到位,就会出现线程卡死、资源泄漏、shutdownNow() 失效等问题。
中断信号怎么被接收和感知
中断本质是一个布尔标志位,由其他线程调用 thread.interrupt() 设置为 true。但 JVM 只在少数阻塞方法中主动响应这个标志:
-
Thread.sleep()、Object.wait()、Thread.join() -
BlockingQueue.take()、BlockingQueue.poll(timeout) -
LockSupport.park()、Selector.select()等
这些方法一旦检测到中断标志为 true,会立即:
- 抛出
InterruptedException - 自动将中断状态设为 false(标志被清除)
非阻塞代码(比如纯计算循环)完全不会触发异常,必须手动轮询:Thread.currentThread().isInterrupted()。
立即学习“Java免费学习笔记(深入)”;
捕获 InterruptedException 后必须恢复中断状态
这是最容易出错也最关键的一环。因为异常抛出时中断标志已被清空,若不手动重置,上层逻辑(如外层循环、线程池管理器)就再也看不到中断意图。
正确做法是在 catch 块中立刻执行:
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复标志
// 然后退出或清理
return;
}
反例包括:
- 只写
e.printStackTrace()或空catch - 捕获后调用
Thread.interrupted()(它会再次清标志) - 恢复中断后继续循环而不退出
循环任务中要主动检查中断状态
绝大多数后台线程都运行在循环中,仅靠阻塞点响应远远不够。必须在循环开头或关键节点插入检查:
- 用
!Thread.currentThread().isInterrupted()作循环条件(不是!Thread.interrupted()) - 长耗时操作(如解析大文件、处理批量数据)后应再检查一次
- 阻塞操作前、后都建议检查,确保中断不被“漏过”
例如:
while (!Thread.currentThread().isInterrupted()) {
try {
String line = reader.readLine(); // 可能阻塞
if (line == null) break;
process(line);
} catch (IOException e) {
break;
}
// 处理完一行后主动确认是否该停
if (Thread.currentThread().isInterrupted()) {
break;
}
}
中断后必须完成清理并安全退出
收到中断不是“暂停”,而是“终止当前任务”。不能继续执行无效逻辑,更不能跳过资源释放。
标准响应流程是三步走:
- 清理:关闭流、释放锁、取消注册监听器、回滚临时状态
-
恢复中断标志:
Thread.currentThread().interrupt() -
退出路径:用
return、break,或抛出自定义运行时异常(避免吞掉信号)
尤其注意 I/O 类中断(如 InterruptedIOException):需立即关闭 Socket、Channel 或 InputStream,不要在 finally 里再调用 sleep() 等阻塞操作。


















