MST

星途 面试题库

面试题:Java线程池提交任务时,如何处理任务执行过程中抛出的异常?

假设使用Java线程池提交任务,任务在执行过程中可能抛出多种异常。请说明使用execute和submit方法提交任务时,分别如何捕获和处理这些异常,并且阐述自定义线程池拒绝策略中处理异常的方式与常规提交任务处理异常方式的关联和区别。
43.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

使用execute方法提交任务捕获异常

  1. 直接捕获:在任务的run方法内部进行异常捕获。
Runnable task = () -> {
    try {
        // 任务逻辑
    } catch (Exception e) {
        // 异常处理
    }
};
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(task);
  1. 通过UncaughtExceptionHandler
    • 实现Thread.UncaughtExceptionHandler接口。
    • 为线程池中的线程设置该处理器。
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 异常处理
    }
}
ExecutorService executorService = Executors.newFixedThreadPool(10);
((ThreadPoolExecutor) executorService).getThreadFactory().newThread(() -> {}).setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Runnable task = () -> {
    // 任务逻辑,不捕获异常
};
executorService.execute(task);

使用submit方法提交任务捕获异常

  1. 通过Future获取结果时捕获
ExecutorService executorService = Executors.newFixedThreadPool(10);
Callable<Integer> task = () -> {
    // 任务逻辑,可能抛异常
    return 1;
};
Future<Integer> future = executorService.submit(task);
try {
    Integer result = future.get();
} catch (InterruptedException | ExecutionException e) {
    if (e instanceof ExecutionException) {
        Throwable cause = e.getCause();
        // 处理任务中抛出的异常
    }
}

自定义线程池拒绝策略中处理异常

  1. 关联
    • 常规提交任务处理异常是针对单个任务执行过程中的异常。
    • 自定义线程池拒绝策略处理异常是在任务因线程池已满等原因无法被接受执行时的异常处理,两者都是为了保障系统在异常情况下的稳定性。
  2. 区别
    • 常规提交任务处理异常:主要关注任务本身执行逻辑中的异常,确保任务内部错误得到妥善处理,保证单个任务的正确执行。
    • 自定义线程池拒绝策略处理异常:关注线程池整体状态导致任务无法提交执行的情况,如线程池队列已满且最大线程数已达到上限等,目的是在这种系统级异常情况下做出合理决策,如记录日志、抛出特定异常等,以保障线程池和整个应用的稳定性。 例如,自定义拒绝策略可以这样实现:
class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        try {
            // 可以尝试将任务放入其他队列或做特殊处理
        } catch (Exception e) {
            // 处理因拒绝任务而产生的异常
        }
    }
}
ThreadPoolExecutor executorService = new ThreadPoolExecutor(
    10, 20, 10, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(5),
    new MyRejectedExecutionHandler());