Java8 ForkJoinPool和Executors.newWorkStealingPool之间的详细区别?

bit*_*007 15 multithreading executorservice fork-join executors forkjoinpool

使用中的低级差异是什么:

ForkJoinPool = new ForkJoinPool(X);
Run Code Online (Sandbox Code Playgroud)

ExecutorService ex = Executors.neWorkStealingPool(X);
Run Code Online (Sandbox Code Playgroud)

其中X是所需的并行级别,即线程运行..

根据文档我发现它们相似.还告诉我哪一个在任何正常用途下更合适和安全.我有1.3亿个条目写入BufferedWriter并使用Unix排序按第1列排序.

另请告诉我如果可能的话要保留多少个线程.

注意:我的系统有 8个核心处理器和 32 GB RAM.

Dav*_*aim 23

工作窃取是现代线程池使用的一种技术,用于减少对工作队列的争用.

经典线程池有一个队列,每个线程池线程锁定队列,使任务出列,然后解锁队列.如果任务很短并且有很多任务,那么队列上存在很多争用.使用无锁队列确实有帮助,但并不能完全解决问题.

现代线程池使用工作窃取 - 每个线程都有自己的队列.当线程池线程产生一个任务时 - 它将它排入自己的队列.当线程池线程想要使任务出列时 - 它首先尝试将任务从自己的队列中出列,如果它没有任何 - 它从其他线程队列中"窃取"工作.这确实减少了theradpool的争用并提高了性能.

newWorkStealingPool 创建一个利用工作用途的线程池,其线程数为处理器数.

newWorkStealingPool提出了一个新问题.如果我有四个逻辑核心,那么池总共有四个线程.如果我的任务阻止 - 例如在同步IO上 - 我没有充分利用我的CPU.我想要的是在任何给定时刻的四个活动线程,例如 - 加密AES的四个线程和等待IO完成的另外140个线程.

这就是ForkJoinPool提供 - 如果您的任务产生新任务并且任务等待它们完成 - 池将注入新的活动线程以使CPU饱和.值得一提的是,ForkJoinPool利用偷工作也是如此.

哪一个用?如果您使用fork-join模型或者您知道任务无限期阻塞,请使用ForkJoinPool.如果您的任务很短并且主要受CPU限制,请使用newWorkStealingPool.

在说完任何事情之后,现代应用程序倾向于使用具有可用处理器数量的线程池,并利用异步IO和无锁容器来防止阻塞.这(通常)给出了最佳性能.

  • 啊,是时候怀旧了。这是一个很棒的答案! (3认同)
  • 为了让 F/J 池为阻塞线程创建一个新的工作线程,请使用 ForkJoinPool.ManagedBlocker。但是,对于阻塞在 I/O 上的 140 个线程,您最终可能会得到 140 个新线程。 (2认同)

Yam*_*cha 7

newWorkStealingPool是更高级别的抽象ForkJoinPool

如果您查看 Oracle jvm 实现,它只是一个预先配置的ForkJoinPool

public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),
                            ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                            null, 
                            true);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,查看实现并不是理解类目的的正确方法。

也归功于:https : //dzone.com/articles/diving-into-java-8s-newworkstealingpools