在 Java 中,ExecutorService 本身不会自动把任务里的异常抛出来,如果处理不当,异常很容易被“吞掉”。下面按常见场景系统说明如何处理异常。
Runnable 任务executor.execute(() -> {
throw new RuntimeException("error");
});
特点:
executor.execute(() -> {
try {
// 业务逻辑
} catch (Exception e) {
log.error("task error", e);
}
});
ThreadFactory factory = r -> {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler((thread, e) -> {
log.error("thread error", e);
});
return t;
};
ExecutorService executor = Executors.newFixedThreadPool(2, factory);
Callable 任务(推荐)Future<Integer> future = executor.submit(() -> {
throw new RuntimeException("error");
});
关键点:
Future 中future.get() 时才会抛出try {
future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause(); // 真正的异常
log.error("task failed", cause);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
✅ 这是最推荐的方式
invokeAll / invokeAnyList<Future<T>> futures = executor.invokeAll(tasks);
for (Future<T> f : futures) {
try {
f.get();
} catch (ExecutionException e) {
// 处理异常
}
}
static <T> Callable<T> wrap(Callable<T> task) {
return () -> {
try {
return task.call();
} catch (Exception e) {
log.error("task error", e);
throw e;
}
};
}
@Async
public void asyncTask() {
throw new RuntimeException("error");
}
配置:
@Bean
public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() {
return (ex, method, params) -> log.error("async error", ex);
}
| 情况 | 结果 |
|---|---|
execute() 抛异常 |
被吞,除非有 UncaughtExceptionHandler |
submit() 不调用 get() |
异常永远不会知道 |
| 线程池满 + 拒绝策略 | 可能直接丢任务 |
| 异常被 catch 后不处理 | 等于没记录 |
✅ 优先使用 Callable + Future.get()
✅ 业务代码内部 try-catch
✅ 线程池统一异常日志
✅ 不建议依赖 UncaughtExceptionHandler 作为主手段
如果你愿意,我可以:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。