ExecutorService 和 ForkJoinPool

ExecutorService and ForkJoinPool

我创建了一个 ExecutorService,如下所示 -

ExecutorService executorSer = Executors.newFixedThreadPool(SIZE);

我有一个元素列表 (LIST) 和一个操作(称为 A),我需要将其应用于此列表中的每个元素。该列表可以包含 1 到 1000 之间的任意数量的元素。 该操作的类型为 Callable。 在 Operation-A 内部,它调用另外 2 个服务 B 和 C。 B和C也是运行作为异步操作提交到同一个线程池

我已经为每个任务创建了一个异步任务来并行执行它,如下所示:

CompletionService<T> completionService =  new ExecutorCompletionService<T>(executorSer);
completionService.submit(A)  // this returns a Future<T>

现在我有一个 Future 列表,我循环它以获取()结果。

如果我有一个非常大的线程池和 LIST 中的少量元素,一切都很好。 但是,如果线程池SIZE小而LIST大小大,i运行就会陷入死锁。 这是因为Operation-A的所有请求都被快速提交,占用了线程池中的所有线程。并且每个操作 A 都在它提交的操作 B 和 C 的 Future.get() 上被阻止。操作 B 和 C 任务只是坐在队列中等待获取线程。

所以,为了解决这个问题,我改用了 ForkJoinPool。我只是用 ForkJoinPool 替换了 newFixedThreadPool 如下

ExecutorService executorSer = new ForkJoinPool(SIZE); 

其余代码保持不变。

这解决了我的问题。如果线程池 SIZE 较小且 LIST 大小较大,则现在不会出现死锁。 我的问题是,为什么? 此外,当我打印线程名称时,我看到线程号大于 SIZE。是否只是生成新线程来解决死锁?

java.util.concurrent.Executorsclass中没有Executors.ForkJoinPool(SIZE)方法。但是,有 Executors.newWorkStealingPool(int parallelism) 方法可以创建 ForkJoinPool。正如 JAVA API 提到的那样:

The parallelism level corresponds to the maximum number of threads actively engaged in, or available to engage in, task processing. The actual number of threads may grow and shrink dynamically.

有你的答案。您提供的参数不是执行程序将管理的实际线程的最大数量(就像 FixedThreadPool 执行程序的情况一样)。