当前位置: 首页 > 面试题库 >

与Java-7 ForkJoinPool相比,Java-5 ThreadPoolExecutor有什么优势?

诸葛雨泽
2023-03-14
问题内容

Java
5以Executor框架的形式引入了对线程池执行异步任务的支持,其核心是java.util.concurrent.ThreadPoolExecutor实现的线程池。Java
7以java.util.concurrent.ForkJoinPool的形式添加了备用线程池。

查看它们各自的API,ForkJoinPool在标准情况下提供了ThreadPoolExecutor功能的超集(尽管严格来说,ThreadPoolExecutor比ForkJoinPool提供了更多的调优机会)。再加上这样的观察,即fork
/
join任务似乎更快(可能是由于工作窃取调度程序所致),肯定需要更少的线程(由于非阻塞的join操作),人们可能会觉得ThreadPoolExecutor已被ForkJoinPool。

但这真的正确吗?我已阅读的所有材料似乎总结出两种类型的线程池之间的模糊对比:

  • ForkJoinPool适用于许多独立的,任务生成的,短暂的,几乎没有阻塞(即计算密集型)的任务
  • ThreadPoolExecutor用于很少的,独立的,外部生成的,较长的,有时是阻塞的任务

这种区别是正确的吗?我们能说些什么更具体吗?


问题答案:

ThreadPool(TP)和ForkJoinPool(FJ)针对不同的用例。主要区别在于不同执行者使用的队列数量决定了哪种类型的问题更适合任一执行者。

FJ执行程序具有n个(又是并行度级别)单独的并发队列(双端队列),而TP执行器只有一个并发队列(这些队列/双端队列可能是不遵循JDK Collections
API的自定义实现)。因此,在您生成大量(通常运行时间相对较短)任务的情况下,FJ执行程序的性能会更好,因为独立队列将最大程度地减少并发操作,而很少的窃取将有助于负载平衡。在TP中,由于只有一个队列,所以每次将工作出队时都会有并发操作,这将成为一个相对的瓶颈并限制性能。

相反,如果长期运行的任务相对较少,则TP中的单个队列不再是性能的瓶颈。但是,n个独立的队列和相对频繁的偷窃尝试现在将成为FJ的瓶颈,因为可能会有许多徒劳的偷窃尝试,这会增加开销。

此外,FJ中的工作窃取算法假设从双端队列中窃取的(较旧的)任务将产生足够的并行任务以减少窃取次数。例如,在快速排序或合并排序中,较旧的任务相当于更大的阵列,这些任务将生成更多任务,并使队列为非空,并减少总体窃取次数。如果在给定的应用程序中不是这种情况,那么频繁的窃取尝试将再次成为瓶颈。ForkJoinPool的javadoc中也指出了这一点:

此类提供状态检查方法(例如getStealCount()),旨在帮助开发,调整和监视fork / join应用程序。



 类似资料:
  • 问题内容: 用…实现事情 似乎 已经 很简单 了… 与 ngResource相比 ,使用Restangular 有哪些优点/缺点? 1.1.3 将返回承诺,并且可以使用[最新的PRcommit来实现。将来会提供支持来支持Restangular所做的其他动词吗?如果发生这种情况,Restangular似乎将消失并变得不耐烦。 问题答案: 我是Restangular的创建者。 我已经在自述文件中创建了

  • 问题内容: 从2010年的计算机语言基准游戏中可以看出: Go平均比C慢10倍 Go比Java慢3倍! 考虑到Go编译器会生成要执行的本机代码,这怎么可能? Go的编译器不成熟?还是Go语言存在一些内在问题? 编辑: 大多数答案否认Go语言的内在缓慢,声称问题出在不成熟的编译器中。 因此,我进行了一些自己的测试来计算斐波那契数:迭代算法在Go(freebsd,6g)中以与C(带有O3选项)一样的速

  • 我对Spring框架相当陌生,所以我为这个愚蠢的问题道歉。我一直在学习Javabean;我也一直在阅读Spring框架是如何成为bean容器的,以及如何有不同类型的bean(使用JavaBeans的优势是什么?)。 然而,我仍然不明白他们为什么如此强大。如果我们想,比如说,创建一个Spring web应用程序,我们不能不使用bean,而只使用POJO吗?与POJO相比,使用Java bean的真正

  • 问题内容: 我对C#非常熟悉,但是开始在Java中工作更多。我希望了解到Java中的枚举基本上与C#中的枚举等效,但是显然并非如此。最初,我很高兴得知Java枚举可以包含多条数据,这似乎非常有利(http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html)。但是,从那时起,我发现了很多C#缺少的功能,例如能够轻松地将枚举元素分配给某个值

  • 问题内容: 最近,我正在与另一位程序员讨论重构充满“ if”语句的巨大(1000行)方法的最佳方法。 该代码是用Java编写的,但我想这个问题也可能在其他语言(例如C#)中发生。 为了解决这个问题,他建议使用责任链模式。他建议开设一个基本的“处理程序”类。然后,“ Handler1”,“ Handler2”等将扩展“ Handler”。 然后,处理程序将具有“ getSuccessor”方法,该方

  • 问题内容: 与常规Python列表相比,NumPy有什么优势? 我有大约100个金融市场系列,我将创建一个100x100x100 = 1百万个单元的多维数据集数组。我将每个x与y和z回归(3变量),以用标准误差填充数组。 我听说对于“大型矩阵”,出于性能和可伸缩性的原因,我应该使用NumPy而不是Python列表。事实是,我知道Python列表,它们似乎对我有用。 如果我转到NumPy,会有什么好