Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程池:是有很多较小的任务更好,还是有较少的任务和较大的批处理更好_Java_Multithreading_Threadpool - Fatal编程技术网

Java线程池:是有很多较小的任务更好,还是有较少的任务和较大的批处理更好

Java线程池:是有很多较小的任务更好,还是有较少的任务和较大的批处理更好,java,multithreading,threadpool,Java,Multithreading,Threadpool,我们目前正试图通过在java应用程序中使用多线程来调整性能。 我们有一个长时间运行的串行任务,我们希望将其拆分为多CPU核 基本上,我们有一个清单,上面有10万件要做的事情 我现在的问题是这样做是否更好: 选项1(伪代码): (i=0;i

我们目前正试图通过在java应用程序中使用多线程来调整性能。 我们有一个长时间运行的串行任务,我们希望将其拆分为多CPU核

基本上,我们有一个清单,上面有10万件要做的事情

我现在的问题是这样做是否更好:

选项1(伪代码):

(i=0;i<100000;i++)的
{
提交(新MyCallable(“1件事要做”))
}
这将向线程池的队列(当前LinkedBlockingQueue)添加100000个可运行/可调用项

还是最好是: 选项2(伪代码)

(i=0;i<4;i++)的
{
提交(新MyCallable(“25000件事要做”))
}
我们已经尝试了选项1,但没有注意到任何性能改进,尽管我们可以清楚地看到多个线程正在疯狂地工作,并且使用了4个CPU核。但我的感觉是,由于任务很多,选项1中存在一些开销。我们还没有尝试过选项2,但我的感觉是,它可以加快速度,因为开销更少。我们基本上是将列表分成4个较大的块,而不是100000个单个项目

有什么想法吗


感谢您的分析是正确的:批处理项目的成本(内存、上下文切换和一般指令计数)会更低,至少一般来说是这样


但是,随着单个任务的增加,这一点变得越来越不相关——如果您已经将99%的时间花在了工作上,而不是线程池开销或对象创建上,那么您只能以这种方式优化剩下的1%。

好吧,这取决于您的用例

就性能而言,我认为拥有更大的工作块比拥有更小的线程要好。上下文切换将更少,因此,您将能够节省CPU周期和RAM


当任务数量较少时,这可能没什么大不了的,但是,如果你有10000个线程,这确实很重要。

重要的是你最小化了上下文切换的数量,并最大化了每个任务的计算工作量。实际上,如果您的任务是计算,那么超过物理CPU的数量是没有帮助的。如果您的任务实际上执行了大量的I/O和I/O等待,那么您希望有许多I/O等待,因此当一个任务阻塞时,总是有一堆“就绪”任务可用


如果你真的有25000件事情要做,而事情是计算,我可能会设置32个线程(比你有更多的CPU,但不会有太多额外的开销),如果这些单元相对较小,我会为每个线程分配10-50个工作单元。

你的机器中有N个内核。您希望以最小的开销使用所有内核。因此,如果任务大小相等,则任务的最小数量可能为N。如果它们不相等,则使用M*N任务可能会更好,因为这意味着即使某些任务相对较短,所有核心都同样繁忙。e、 一个核心做一个长任务,另一个做三个短任务。我在大多数用例中使用2-4的M

如果可以,您可以对要首先开始的较长时间运行的任务进行排序,以获得最佳平衡。i、 e.在添加任务之前,将任务从最长到最短排序


e、 g.如果您有8个内核,您可能会发现8个任务最适合CPU限制的处理。对于IO绑定的处理或需要不同时间的任务,2*8到4*8任务可能是最佳的。

4个批处理的问题可能是,如果其中一个批处理在10分钟内完成,而其中三个批处理在20分钟内完成,那么10分钟内将不使用1个核心,而其他3个线程将在3个核心上处理项目。但你说得对。但是验证的唯一方法是检查它,因为很多事情都取决于你的数据。

对此没有一个通用的答案;这取决于“要做的事情”的性质。你必须进行实验。谢谢你提供的有用的答案。我知道没有通用的答案,但我想了解每种方法。我们的用例是计算密集型的,而不是I/O限制型的。我们现在将实施选项2并比较结果。
for(i = 0; i < 100000; i++){
  threadpool.submit(new MyCallable("1 thing to do"))
}
for(i = 0; i < 4; i++){
  threadpool.submit(new MyCallable("25000 things to do"))
}