You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线程任务抛出异常时终止ExecutorService后续任务并捕获异常的方案咨询

解决方案

问题根因

你原有代码的问题出在两点:

  • 向ExecutorService提交Callable任务后,异常会被封装在返回的Future对象中,你没有主动调用Future.get()方法,所以异常直接被吞掉,外层catch自然捕获不到任何内容。
  • 你提交完所有任务后直接调用threadPool.shutdown(),会等待所有已提交的任务执行完成,自然不会停止未开始的任务。

常见误解澄清

你担心的「等待Future返回会阻塞其余线程运行」是完全不存在的:线程池的worker线程是独立运行的,主线程调用ExecutorCompletionService.take()只是按完成顺序获取已结束的任务结果,不会对正在运行的worker线程产生任何阻塞影响,完全不会违背多线程并发设计的初衷。

实现代码

你只需要调整原有主线程的逻辑,提交完任务后循环拉取已完成的任务结果,一旦捕获到异常立刻终止线程池即可:

import java.util.concurrent.*;

public class Test {
    public static void main(String[] args) {
        final ExecutorService threadPool = Executors.newFixedThreadPool(4);
        final ExecutorCompletionService<Void> completionService = new ExecutorCompletionService<>(threadPool);
        int taskCount = 10;

        try {
            for (int i = 0; i < taskCount; i++) {
                int b = i;
                completionService.submit(() -> doSomeWork(b));
            }

            // 循环拉取已完成的任务,共taskCount个
            for (int i = 0; i < taskCount; i++) {
                Future<Void> finishedFuture = completionService.take();
                finishedFuture.get(); // 这里会抛出任务执行时的异常
            }

            // 所有任务正常完成才会走到这里
            threadPool.shutdown();
            threadPool.awaitTermination(1, TimeUnit.HOURS);
            System.exit(0);

        } catch (ExecutionException e) {
            // 捕获到任务抛出的异常
            System.out.println("Something wrong happened: " + e.getCause().getMessage());
            // 立刻终止线程池:清空等待队列的未执行任务,给正在运行的线程发中断信号
            threadPool.shutdownNow();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            threadPool.shutdownNow();
        }

        System.exit(1);
    }

    //该函数有50%概率抛出异常
    public static Void doSomeWork(int i) throws Exception {
        Thread.sleep(500);
        if ((Math.random() > 0.5)) {
            System.out.println("I have reached indice: " + i);
        } else {
            throw new Exception("I couldn't handle indice " + i);
        }
        return null;
    }
}

效果说明

以上代码运行后完全符合你的预期:

  1. 只要有任意一个任务抛出异常,主线程会立刻捕获到异常
  2. 调用shutdownNow()后,所有还在队列中未开始执行的任务会被直接清空,不会再运行
  3. 正在运行的任务如果包含Thread.sleep这类响应中断的逻辑,会立刻抛出InterruptedException终止运行,实现最快停止的效果

内容的提问来源于stack exchange,提问作者Mit94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:48:02