ForkJoinPool.commonPool()和新的ForkJoinPool(availableCPU-1)有什么区别?

时间:2019-02-04 22:38:46

标签: java multithreading forkjoinpool

在我的代码中,我有一个包含静态最终变量的类

private static final ForkJoinPool pool = new ForkJoinPool(availableCPUs - 1);

我有一个长时间运行的任务提交给池,它将占用所有CPU资源。提交的任何其他任务将被挂起。 但是,当我切换为创建公共池

private static final ForkJoinPool pool = ForkJoinPool.commonPool();

所有任务都可以提交并执行。

我只是想知道这两段代码之间的区别。 commonPool()仍然呼叫new ForkJoinPool()并传递availableCPUs - 1

我还注意到commonPool()使用类型为SafeForkJoinWorkerThreadFactory的工厂,而new ForkJoinPool()使用ForkJoinPool$DefaultForkJoinWorkerThreadFactory。这有关系吗?

非常感谢您!

2 个答案:

答案 0 :(得分:0)

Documentation说:

  

默认情况下,公共池是使用默认参数构造的。

  

ForkJoinPool()

     

使用Runtime.availableProcessors(),无UncaughtExceptionHandler和非异步LIFO处理模式,创建并行度等于default thread factoryForkJoinPool

那么,什么使您认为new ForkJoinPool(availableCPUs - 1)ForkJoinPool.commonPool()是相同大小的池?

如果您只有2个CPU,那么availableCPUs - 1意味着您正在创建一个1个线程的池,即它一次只能处理一个任务,因此长时间运行的任务将阻止所有其他任务。

但是availableProcessors()具有2个CPU,这意味着您将获得一个具有2个线程的公用池,即它可以在处理一个长期运行的任务时处理其他任务。

答案 1 :(得分:0)

我想我明白了。

ForkJoin维护两种类型的队列:一个普通的入站队列和每个工作线程的工作线程队列。所有工作线程将首先从常规入站队列中获取并填充其工作线程。一个工作线程完成其工作队列中的所有任务后,将尝试从其他工作线程中窃取。如果没有其他任务要从其他工作线程中窃取,则工作线程将再次从常规入站队列中获取。

但是,对于公共池,主线程也将有助于处理任务。但是,主线程没有工作队列。因此,完成一项任务后,主线程将能够从常规入站队列中获取。

由于默认情况下,ForkJoin队列为LIFO,因此主线程将能够提取最后提交的任务。