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

为什么使用ForkJoinPool提交任务会出现执行两次的情况?

代码复现
import java.util.concurrent.ForkJoinPool;

public class Test {
  public static void main(String[] args) {
    ForkJoinPool forkJoinPool = new ForkJoinPool(3);
    forkJoinPool.submit(() -> {
      System.out.println("Inside...");
    }).invoke();
  }
}
两次打印的原因
  • ForkJoinPool.submit()会把任务提交到池的共享调度队列,池内的工作线程会异步抢占执行该任务。
  • 后续你调用了submit返回的ForkJoinTask的invoke()方法,由于调用方是普通的main线程,不属于当前ForkJoinPool的工作线程,触发了ForkJoin的外部线程协助执行逻辑:main线程会直接尝试执行这个未完成的任务,不需要等待池内线程调度。
  • 此时存在竞态条件:如果submit提交任务后,池内的工作线程已经取出了任务、但还没来得及更新任务的执行状态,main线程调用invoke()时会判定任务还没执行,也会启动任务执行,最终同一个任务被池线程和main线程各执行一次,就会出现两次打印。
  • 这个现象不是必现的,和CPU调度有关:如果池内线程已经执行完任务,main线程调用invoke()时只会拿结果,不会重复执行,就只会打印一次。
修复方案

要保证任务只执行一次,选任意一种改法即可:

  1. 提交异步任务后用join()等待结果,不要调用invoke():
forkJoinPool.submit(() -> {
  System.out.println("Inside...");
}).join();
  1. 不需要异步提交的话,直接用ForkJoinPool.invoke()提交任务,不用先submit:
forkJoinPool.invoke(() -> {
  System.out.println("Inside...");
});

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

相关产品推荐
方舟 Agent Plan

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

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