java传递给ThreadPoolExecutor/ScheduledThreadPoolExecutor的建议corePoolSize是多少?
传递给ThreadPoolExecutor/ScheduledThreadPoolExecutor的建议corePoolSize是多少
Runtime.getRuntime().availableProcessors()
?
Runtime.getRuntime().availableProcessors() * 2
从一个角度来说,我希望CPU(所有核心)的利用率达到100%,但线程数量要尽可能少,以便它们尽快完成,并且不会对上下文切换造成太大的影响
另一方面,一些线程可能不会一直使用CPU,比如等待网络。在这种情况下,我希望生成新线程,并让所有核心保持忙碌
如果CPU暂时过度使用,我没问题。优于使用不足和未处理的任务
那么如何实现线程负载平衡呢?谢谢
# 1 楼答案
除了约翰16384的回答之外:
如果您的CPU支持每个CPU核心两个线程(多线程),那么代码
Runtime.getRuntime().availableProcessors()? Runtime.getRuntime().availableProcessors() * 2
可能是一个好主意# 2 楼答案
调整线程池大小取决于要在该池上执行的任务的性质。一般来说,这取决于等待时间和cpu时间之间的比率以及可用cpu的数量
适用的一般公式为:
将处理器保持在所需利用率的最佳池大小为:
您可以在Java Concurrency In Practice的8.2调整线程池大小部分找到更多信息
# 3 楼答案
您可以查看Amdahl's law来定义核心的数量。把你的程序当作一个单线程程序,看看你可以在哪里并行化。这可以给您一个N的概念(这里我们可以通过应用程序的线程数来近似计算内核数)
根据我的经验,确定“最佳”线程数的最佳方法仍然是创建多线程程序,并使用尽可能多的线程数值进行测试,看看哪一个线程输出的性能最好。(另见Optimal number of threads per core)
# 4 楼答案
我想这将取决于你在做什么。您已经暗示一些线程可能正在等待I/O
corePoolSize
是池将保留的线程数,即使空闲。我想您应该设置最大池大小上下文切换开销总是存在的,我不认为它会随着线程的增加而增加,因为切换通常是作为常量片实现的(即,时间片的减少不会与可运行线程的数量成反比)
显然,要实现满负载,您至少需要与内核数量相同的线程,需要多少额外线程取决于线程完成的速度和I/O所需的时间
一种选择是在具有较大池大小的单独步骤中执行I/O,这样您就可以确保始终有一个已经完成了I/O步骤(CompletableFuture对此很方便)。然后,在下一步中,您将使用一个单独的线程池,该线程池大小与一个线程完成后从上一步输入的内核数相同
类似这样的内容(未经验证):