interrupt() 是协作式中断信号而非强制终止,仅设置中断标志位;线程是否响应取决于自身是否检查标志或调用可中断阻塞方法,否则中断无效。

因为 interrupt() 从来就不是“强行终止”机制,它只是设置一个中断标志位,线程是否停止,完全取决于线程自己有没有检查这个标志、有没有响应被中断的阻塞调用。
interrupt() 的本质是协作信号,不是强制指令
调用 shutdownNow() 时,线程池会遍历所有活跃工作线程,对每个线程调用 interrupt()。但该方法仅做一件事:把目标线程的中断状态设为 true。它不会暂停 CPU、不会注入 kill 指令、也不会修改栈帧或强制退出循环。如果线程正在纯计算(比如密集循环 + 数值运算),且循环体中既没调用 sleep()/wait()/join() 等可中断阻塞方法,也没主动调用 isInterrupted() 判断,那这个中断信号就一直“悬着”,毫无作用。
死循环里不检查中断,等于没收到通知
常见错误写法:
-
while (true) { doHeavyCalc(); }—— 完全忽略中断标志 -
while (!Thread.interrupted()) { ... }—— 错用静态方法,每次调用都清空标志,导致第二次判断永远为 false -
while (!Thread.currentThread().isInterrupted()) { ... }写对了条件,但循环体内有queue.take()却没包 try-catch,或捕获InterruptedException后只打印日志、不恢复中断也不 break
阻塞调用才是中断生效的关键入口
只有当线程处于以下状态之一时,interrupt() 才会触发实际行为:
- 正在执行
Thread.sleep()、Object.wait()、Thread.join() - 正在调用
BlockingQueue.take()、LinkedTransferQueue.poll()等并发工具类的阻塞方法 - 使用
LockSupport.park()或 NIO 的可中断通道(如SocketChannel.read())
这些方法内部会检查中断状态,若发现已中断,则抛出 InterruptedException 并自动清除中断标志。但注意:一旦抛出异常,**必须在 catch 块中调用 Thread.currentThread().interrupt() 恢复标志**,否则外层 while 循环的条件判断将失效。
真正可靠的退出方式需要双保险
单靠中断在复杂场景下容易失效,推荐组合策略:
- 用
volatile boolean running = true作为主控开关,外部可直接设为false - 循环条件写成
while (running && !Thread.currentThread().isInterrupted()) - 阻塞操作统一放在 try-catch 中,catch 里先恢复中断再 break
- 避免在循环内做不可中断的 I/O(如老式
InputStream.read()),优先替换为 NIO 或带超时的封装
不复杂但容易忽略。










