multithreading - Java8 ForkJoinPool 和 Executors.newWorkStealingPool 的详细区别?

标签 multithreading executorservice fork-join executors forkjoinpool

使用之间的低级区别是什么:

ForkJoinPool = new ForkJoinPool(X);


ExecutorService ex = Executors.neWorkStealingPool(X);

在哪里 X 是所需的并行级别,即线程正在运行..

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

如果可能的话,还让我知道要保留多少线程。

注:我的系统有 8 核心处理器和 32 GB 内存。

最佳答案

工作窃取是现代线程池用来减少工作队列争用的一种技术。

经典的线程池有一个队列,每个线程池线程锁定队列,使任务出队,然后解锁队列。如果任务很短而且数量很多,那么队列上就会出现很多争用。使用 无锁 queue 在这里确实有帮助,但并不能完全解决问题。

现代线程池使用 偷工作 - 每个线程都有自己的队列。当一个线程池线程产生一个任务时——它将它排入自己的队列。当一个线程池线程想要使一个任务出队时——它首先尝试将一个任务从他自己的队列中出队,如果它没有任何任务——它从其他线程队列中“窃取”工作。这确实减少了线程池的争用并提高了性能。
newWorkStealingPool创建一个使用工作窃取的线程池,其中线程数作为处理器数。
newWorkStealingPool提出了一个新问题。如果我有四个逻辑核心,那么池将总共有四个线程。如果我的任务阻塞 - 例如在同步 IO 上 - 我没有充分利用我的 CPU。我要的是四个活跃 上的线程任何给定时刻 ,例如 - 加密 AES 的四个线程和等待 IO 完成的另外 140 个线程。

这就是 ForkJoinPool提供 - 如果您的任务产生新任务并且该任务等待它们完成 - 池将注入(inject)新的事件线程以使 CPU 饱和。值得一提的是ForkJoinPool也利用工作窃取。

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

话虽如此,现代应用程序倾向于使用具有可用处理器数量的线程池,并利用 异步IO 无锁容器为了防止阻塞。这(通常)提供最佳性能。

关于multithreading - Java8 ForkJoinPool 和 Executors.newWorkStealingPool 的详细区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41337451/

相关文章:

java - 如何在jsp文件中显示Java多线程输出

在 C 中复制对数组的引用

C# 进程 - 完成前暂停或 sleep

java - BlockingQueue的put()和高并发

java - 为什么静态初始化器中带有 lambda 的并行流会导致死锁?

java - Java 7 的 ForkJoinTask 中的 get() 和 invoke() 有什么区别?

java - 如何在 AsyncTask 中使用 Runnable.wait()?为什么 AsyncTask 不等待...?

java - ScheduledExecutorService 一段时间后未运行

java - 为什么在 java 中使用 ExecutorService 在 exec.shutdown() 之前使用 exec.isTermminate() ?

Java - 如何同步和并行调用返回字符串的函数?