调用Future.get()时需捕获ExecutionException、InterruptedException和CancellationException三种异常;ExecutionException需通过getCause()获取原始异常,InterruptedException应恢复中断状态,CancellationException无嵌套异常。

调用 Future.get() 时,如果子线程执行过程中抛出异常(非 InterruptedException 或 CancellationException),该异常会被包装成 ExecutionException 并在主线程中抛出。要捕获它,需用 try-catch 显式处理,并从 getCause() 中提取原始异常。
正确捕获 ExecutionException
必须将 get() 放在 try 块中,用 catch(ExecutionException e) 捕获,再通过 e.getCause() 获取子线程里真正抛出的异常(如 NullPointerException、IllegalArgumentException 等)。
- 不要只捕获
Exception或Throwable,否则会掩盖异常来源 -
ExecutionException是受检异常,编译器强制要求处理 -
getCause()返回的可能是null(极少见),建议判空
同时处理其他常见异常
Future.get() 还可能抛出另外两种受检异常,需一并处理:
-
InterruptedException:调用线程被中断,通常应恢复中断状态(Thread.currentThread().interrupt()) -
CancellationException:任务被取消后调用get(),无需getCause(),它本身不含嵌套异常
示例代码结构
以下是一个典型的安全调用模式:
立即学习“Java免费学习笔记(深入)”;
try {
String result = future.get(); // 可能抛 ExecutionException
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof NullPointerException) {
// 处理子线程中的 NPE
} else if (cause instanceof IllegalArgumentException) {
// 处理参数错误
} else {
// 兜底:记录日志或重新抛出
log.error("Task failed", cause);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
} catch (CancellationException e) {
// 任务已取消,按业务逻辑处理
}
注意 get() 的阻塞特性
get() 默认会一直阻塞直到任务完成,容易导致主线程卡住。建议:
- 使用带超时的
get(long timeout, TimeUnit unit),避免无限等待 - 超时后会抛
TimeoutException(运行时异常),也应捕获处理 - 若任务未完成,可考虑取消:
future.cancel(true)


















