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

Java中如何等待ExecutorService所有线程执行完成

核心问题说明

  1. 为什么shutdown()没有阻塞?
    ExecutorService#shutdown()的设计逻辑就是非阻塞的:调用后只会停止线程池接收新的任务,已经提交到队列的任务会继续执行,但方法会立即返回,不会等待运行中的任务结束,所以才会出现你看到的Ending shutdown先打印的现象。

  2. 为什么你用awaitTermination()会等满30秒?
    你大概率是调用顺序错了。awaitTermination(long timeout, TimeUnit unit)的作用是等待线程池进入终止状态,触发它返回的条件有三个:

  • 所有已提交的任务全部执行完成
  • 达到设置的超时时间
  • 等待的线程被中断
    *必须先调用shutdown()方法,才会触发线程池的终止流程,否则线程池会一直处于运行状态,awaitTermination()只会等满超时时间才返回。

正确实现方案

方案1:使用 shutdown + awaitTermination 组合(最通用)

修改你的main方法代码即可,所有任务执行完会立刻返回,不会等满30秒:

public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
    final ExecutorService threadPool = Executors.newFixedThreadPool(4);
    final ExecutorCompletionService<Character> completionService = new ExecutorCompletionService<>(threadPool);

    final List<Character> letters = IntStream.range(65, 91).mapToObj(i -> (char) i).collect(Collectors.toList());
    for (char letter : letters) {
        completionService.submit(() -> printLetter(letter));
    }
    
    System.out.println("Starting shutdown");
    // 先调用shutdown停止接收新任务
    threadPool.shutdown();
    // 再等待最多30秒,所有任务执行完会立刻返回
    threadPool.awaitTermination(30, TimeUnit.SECONDS);
    System.out.println("Ending shutdown");
}

方案2:基于ExecutorCompletionService逐个等待任务完成

因为你已经用了ExecutorCompletionService,可以主动获取所有任务的执行结果,不需要设置超时时间,等待所有任务结束后再关闭线程池:

public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
    final ExecutorService threadPool = Executors.newFixedThreadPool(4);
    final ExecutorCompletionService<Character> completionService = new ExecutorCompletionService<>(threadPool);

    final List<Character> letters = IntStream.range(65, 91).mapToObj(i -> (char) i).collect(Collectors.toList());
    int taskCount = letters.size();
    for (char letter : letters) {
        completionService.submit(() -> printLetter(letter));
    }
    
    System.out.println("Starting shutdown");
    // 等待所有任务执行完成,take()会阻塞直到有任务完成
    for (int i = 0; i < taskCount; i++) {
        completionService.take();
    }
    // 所有任务完成后再关闭线程池
    threadPool.shutdown();
    System.out.println("Ending shutdown");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:00:05