捕获 InterruptedException 后必须恢复中断状态,因为 JVM 会自动清空中断标志,若不调用 Thread.currentThread().interrupt() 补回标记,上层逻辑将无法检测中断意图,导致线程无法及时退出。

为什么捕获 InterruptedException 后必须恢复中断状态
当线程在 sleep()、wait()、join() 或 BlockingQueue.take() 等阻塞方法中被中断时,JVM 会自动清空该线程的中断标志(即调用 Thread.interrupted() 的效果),然后抛出 InterruptedException。这意味着:异常一抛出,isInterrupted() 就会返回 false —— 中断信号“消失”了。
如果不手动恢复,上层逻辑(比如任务调度器、ExecutorService 的 shutdownNow()、或外层 while 循环)将无法通过 isInterrupted() 检测到中断意图,导致任务无法及时退出,形成“假活跃”线程。
标准恢复方式:仅在 catch 块中调用 currentThread().interrupt()
正确做法是在 catch 块内第一句就执行:
- Thread.currentThread().interrupt();
这个调用会把中断标志重新设为 true,且不改变其他状态。它不是“重发中断”,而是“补回被 JVM 清掉的那个标记”。
注意两点:
- 不能用 Thread.interrupted() 替代 —— 它是静态方法,会清除状态,且作用于当前线程,容易误判;
- 不能放在 finally 块里 —— 如果异常没发生,finally 仍会执行,可能错误地设置中断状态,干扰正常流程。
根据方法签名选择处理路径
是否恢复中断,取决于你能否把 InterruptedException 向上抛出:
- 若方法声明了 throws InterruptedException(如工具类方法、自定义阻塞操作),应直接抛出,不捕获;
- 若无法抛出(如 Runnable.run()、Callable.call() 未声明该异常、或接口受限),则必须 catch + interrupt() 恢复;
- 若恢复后还需包装为运行时异常(例如统一错误处理),可用 throw new RuntimeException(e),但需确保调用方知情并能响应中断语义。
配合循环使用的典型模式
多数可取消任务都用循环驱动,中断恢复后要配合主动退出逻辑:
- 在循环条件中持续检查 !Thread.currentThread().isInterrupted();
- 捕获异常后恢复中断,并用 break 或 return 显式退出;
- 如有资源需清理(如关闭流、释放锁),应在恢复中断后、退出前完成,保证原子性与可见性。
例如:
while (!Thread.currentThread().isInterrupted()) {
try { doWork(); }
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复
cleanup();
return;
}
}

















