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

Java中ExecutorService任务未并行运行的原因及正确实现方式

关于ExecutorService任务并行执行的疑问解答

你的代码行为是否符合预期?

是的,你的代码行为完全符合ExecutorService的设计预期。Executors.newFixedThreadPool(2)确实会创建一个包含2个工作线程的线程池,任务是在并行执行的——你觉得没有并行,大概率是观察方式的问题。

比如你的任务逻辑是先打印任务信息,然后Thread.sleep(2000)。虽然打印语句的输出可能有先后顺序,但两个工作线程会同时进入睡眠状态,这就是并行的体现。只是单纯的打印顺序无法直观展示时间上的重叠。

如何验证任务确实在并行执行?

你可以给任务添加时间戳,观察任务的启动和结束时间是否重叠:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestExecutor {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 5; i++) {
            int taskId = i;
            executor.submit(() -> {
                long startTime = System.currentTimeMillis();
                System.out.println(
                    "Task " + taskId + " started at " + startTime + " on " + Thread.currentThread().getName()
                );
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                long endTime = System.currentTimeMillis();
                System.out.println(
                    "Task " + taskId + " ended at " + endTime + " on " + Thread.currentThread().getName()
                );
            });
        }

        executor.shutdown();
    }
}

运行后你会看到,前两个任务的启动时间几乎一致,结束时间也几乎一致——这就证明它们是并行执行的。后续的任务会在前两个任务完成后,由空闲的工作线程依次接手。

Java中确保任务并行执行的正确方式

  • 选择合适的线程池大小
    • CPU密集型任务:线程池大小建议设置为CPU核心数 + 1,避免过多上下文切换。
    • IO密集型任务:线程池大小可以设置得更大(比如CPU核心数 * 2或更高),因为线程大部分时间在等待IO操作,更多线程可以提高资源利用率。
  • 避免任务间的不必要同步
    如果多个任务都同步同一个锁对象,或者依赖同一个阻塞资源,会导致任务串行执行。确保任务的核心逻辑没有全局的同步阻塞。
  • 等待任务执行完成
    你的代码中调用了executor.shutdown(),但这个方法只是停止线程池接受新任务,不会等待已有任务执行完毕。建议显式等待任务结束,避免意外:
    executor.shutdown();
    try {
        // 等待10秒,让所有任务完成
        if (!executor.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS)) {
            // 超时后强制关闭线程池
            executor.shutdownNow();
        }
    } catch (InterruptedException e) {
        executor.shutdownNow();
    }
    
  • 确保任务本身适合并行
    如果任务之间存在强依赖(比如必须前一个任务完成后才能执行下一个),那无论线程池多大都无法并行。只有无依赖、可独立执行的任务才能真正并行。

内容的提问来源于stack exchange,提问作者Tahly Yuliana Jiménez Boteo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 06:04:53