温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

ExecutorService怎么处理异常

发布时间:2026-10-06 20:16:11 来源:亿速云 阅读:93 作者:小樊 栏目:编程语言

在 Java 中,ExecutorService 本身不会自动把任务中的异常抛出到主线程,如果处理不当,异常很容易被“吞掉”。下面按使用方式系统说明如何处理异常。


一、不同提交方式下的异常处理

1. execute(Runnable)

executor.execute(() -> {
    throw new RuntimeException("error");
});

✅ 异常会:

  • 被线程的 未捕获异常处理器(UncaughtExceptionHandler) 捕获
  • 不会抛给调用者

处理方式

Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
    System.err.println("Thread " + t.getName() + " error: " + e);
});

或自定义 ThreadFactory:

ThreadFactory factory = r -> {
    Thread t = new Thread(r);
    t.setUncaughtExceptionHandler((t1, e) -> System.err.println(e));
    return t;
};

2. submit(Runnable) / submit(Callable)

Future<?> future = executor.submit(() -> {
    throw new RuntimeException("error");
});

❌ 异常不会立即抛出 ✅ 异常被封装在 Future 中

正确处理方式

try {
    future.get(); // 会抛出 ExecutionException
} catch (ExecutionException e) {
    Throwable cause = e.getCause(); // 真正的异常
    e.printStackTrace();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

⚠️ 如果不调用 get(),异常会被吞掉。


二、推荐做法(生产级)

✅ 方式 1:使用 Callable + Future

最清晰、可控

Future<String> f = executor.submit(() -> {
    if (true) throw new RuntimeException("fail");
    return "ok";
});

try {
    f.get();
} catch (ExecutionException e) {
    log.error("task failed", e.getCause());
}

✅ 方式 2:在任务内部 try-catch(业务异常)

executor.execute(() -> {
    try {
        business();
    } catch (Exception e) {
        log.error("task error", e);
    }
});

适合:

  • 不希望中断线程
  • 异常可恢复或记录即可

✅ 方式 3:自定义 ThreadPoolExecutor 重写 afterExecute

new ThreadPoolExecutor(...) {
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        if (t != null) {
            log.error("task error", t);
        }
        if (r instanceof Future<?>) {
            try {
                ((Future<?>) r).get();
            } catch (ExecutionException e) {
                log.error("future error", e.getCause());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
};

✅ 统一捕获 execute 和 submit 的异常


三、Spring 环境(@Async)

@Async
public void run() {
    throw new RuntimeException("error");
}

✅ 使用:

@Bean
public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() {
    return (ex, method, params) -> log.error("async error", ex);
}

四、总结对照表

提交方式 异常是否抛出 如何处理
execute 否 UncaughtExceptionHandler
submit 否(延迟) future.get()
Callable 否(延迟) future.get()
afterExecute 是 统一处理
Spring @Async 否 AsyncUncaughtExceptionHandler

如果你有具体场景(比如:定时任务 / 批量任务 / 线程池参数),我可以给你一个可直接用的模板代码。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手