遇到 interruptedexception 应立即恢复中断状态、清理资源并退出,不可忽略或仅打印日志;它是协作式取消通知,非错误异常,需通过 thread.currentthread().interrupt() 恢复标记并终止任务。

遇到 InterruptedException,不是简单地捕获后吞掉或打印日志就完事。它本质是线程被主动中断的信号,代表上层希望当前操作停止,必须尊重并传递这一意图。
明确中断语义:它不是异常,而是协作式取消通知
InterruptedException 是受检异常,但设计初衷不是描述“出错了”,而是传达“请尽快退出当前阻塞操作”。JVM 在调用 Thread.interrupt() 后,若线程正处在 wait()、join()、sleep() 或某些 NIO 阻塞调用中,就会抛出该异常,并自动清除线程的中断状态(即 Thread.interrupted() 会返回 false)。
- 不要写成
catch (InterruptedException e) { /* 忽略 */ } - 不要仅记录日志后继续执行原逻辑(比如循环重试)
- 应视作“取消请求已到达”,立刻终止当前任务流程
标准处理三步法:恢复中断 + 清理资源 + 退出
推荐模式:捕获后立即重新设置中断状态,完成必要清理,然后返回或抛出自定义运行时异常(如 RuntimeException 或业务级取消异常)。
- 调用
Thread.currentThread().interrupt()恢复中断标记——让外层代码仍能通过Thread.interrupted()检测到中断 - 释放持有的锁、关闭流、取消注册监听器等清理动作不能跳过
- 避免在
finally块中覆盖中断状态;若需在 finally 中做清理,请先保存中断状态再恢复
在不同场景中的落地示例
比如一个带超时的队列取数操作:
try {
Object item = queue.poll(5, TimeUnit.SECONDS);
if (item != null) process(item);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断
cleanupResources();
throw new TaskCancelledException("Task interrupted during polling");
}
又如在循环中等待条件满足:
while (!ready && !Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复
break; // 立即退出循环
}
}
- 循环体中必须检查
isInterrupted(),否则可能错过中断 - 阻塞方法内部已响应中断,但外层逻辑仍需配合退出
- 使用
LockSupport.parkNanos()等底层工具时,需手动检测Thread.interrupted()
避免常见反模式
这些写法看似能编译通过,实则破坏协作契约:
-
catch (InterruptedException e) { e.printStackTrace(); }—— 中断丢失,调用方无法感知取消 -
catch (InterruptedException e) { Thread.sleep(10); }—— 伪重试,实际是忽略中断并制造新阻塞 - 在
Runnable.run()中捕获后不恢复中断也不退出 —— 线程池中该线程可能持续占用而不响应 shutdown










