在我的代码中,我有一个包含静态最终变量的类
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
。这有关系吗?
非常感谢您!
答案 0 :(得分:0)
默认情况下,公共池是使用默认参数构造的。
使用
Runtime.availableProcessors()
,无UncaughtExceptionHandler和非异步LIFO处理模式,创建并行度等于default thread factory的ForkJoinPool
。
那么,什么使您认为new ForkJoinPool(availableCPUs - 1)
和ForkJoinPool.commonPool()
是相同大小的池?
如果您只有2个CPU,那么availableCPUs - 1
意味着您正在创建一个1个线程的池,即它一次只能处理一个任务,因此长时间运行的任务将阻止所有其他任务。
但是availableProcessors()
具有2个CPU,这意味着您将获得一个具有2个线程的公用池,即它可以在处理一个长期运行的任务时处理其他任务。
答案 1 :(得分:0)
我想我明白了。
ForkJoin维护两种类型的队列:一个普通的入站队列和每个工作线程的工作线程队列。所有工作线程将首先从常规入站队列中获取并填充其工作线程。一个工作线程完成其工作队列中的所有任务后,将尝试从其他工作线程中窃取。如果没有其他任务要从其他工作线程中窃取,则工作线程将再次从常规入站队列中获取。
但是,对于公共池,主线程也将有助于处理任务。但是,主线程没有工作队列。因此,完成一项任务后,主线程将能够从常规入站队列中获取。
由于默认情况下,ForkJoin队列为LIFO,因此主线程将能够提取最后提交的任务。