futuretask响应中断但不主动抛出interruptedexception,而是传递中断状态:未启动时cancel(true)直接标记取消;运行中时尝试中断执行线程;get()被中断则抛interruptedexception,任务结果异常则包装为executionexception。

FutureTask 在执行过程中会响应中断信号,但具体行为取决于任务所处的阶段:未启动、运行中或已完成。关键在于它不会主动抛出 InterruptedException,而是将中断状态传递给内部 Runnable 或 Callable,并在 get() 方法中以 ExecutionException 包装原始异常(包括 InterruptedException)抛出。
任务尚未开始执行时收到中断
如果调用 cancel(true) 且任务还未被线程执行(即处于 NEW 状态),FutureTask 会直接将状态设为 CANCELLED,并设置中断标志。此时线程尚未进入 run(),所以没有实际中断发生,只是标记任务取消成功。
- 调用 cancel(true) 后,isCancelled() 返回 true,isDone() 也返回 true
- 后续调用 get() 会立即抛出 CancellationException
- Runnable/Callable 的 run()/call() 方法根本不会被执行
任务正在执行时被中断
若任务已在某个线程中运行(RUNNING 状态),cancel(true) 会尝试对该线程调用 interrupt()。此时 FutureTask 不会拦截或吞掉中断,而是让中断自然传递到你的任务逻辑中。
- 你的 Callable 中若调用了 Thread.sleep()、Object.wait()、BlockingQueue.take() 等可中断方法,会触发 InterruptedException
- 若任务中未处理中断(比如没捕获 InterruptedException 或没检查 Thread.interrupted()),可能忽略中断继续运行
- get() 方法在等待结果时,若任务因中断而提前结束(例如抛出 InterruptedException),则 get() 抛出 ExecutionException,其 cause 是原始的 InterruptedException
get() 调用期间被中断
当线程在调用 get() 阻塞等待结果时(比如任务还在跑),此时对当前线程调用 interrupt(),FutureTask 会立即响应并抛出 InterruptedException。
- 该中断影响的是调用 get() 的线程,不是执行任务的线程
- 任务本身仍继续运行(除非你额外做了中断传播)
- get() 抛出 InterruptedException 后,线程中断状态会被清除(符合 JDK 中断语义)
- 你可以捕获该异常后决定是否取消任务:future.cancel(true)
正确处理中断的建议
要让 FutureTask 真正支持协作式中断,需在 Callable 实现中主动响应中断信号。
- 在循环中定期检查 Thread.currentThread().isInterrupted()
- 捕获 InterruptedException 后,通常应恢复中断状态:Thread.currentThread().interrupt()
- 避免只吞掉 InterruptedException 而不退出或清理资源
- cancel(true) 不等于“立刻停止”,它只是发送中断信号,任务是否响应由你控制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











