有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java传递给ThreadPoolExecutor/ScheduledThreadPoolExecutor的建议corePoolSize是多少?

传递给ThreadPoolExecutor/ScheduledThreadPoolExecutor的建议corePoolSize是多少

Runtime.getRuntime().availableProcessors()Runtime.getRuntime().availableProcessors() * 2

从一个角度来说,我希望CPU(所有核心)的利用率达到100%,但线程数量要尽可能少,以便它们尽快完成,并且不会对上下文切换造成太大的影响

另一方面,一些线程可能不会一直使用CPU,比如等待网络。在这种情况下,我希望生成新线程,并让所有核心保持忙碌

如果CPU暂时过度使用,我没问题。优于使用不足和未处理的任务

那么如何实现线程负载平衡呢?谢谢


共 (4) 个答案

  1. # 1 楼答案

    除了约翰16384的回答之外:

    如果您的CPU支持每个CPU核心两个线程(多线程),那么代码Runtime.getRuntime().availableProcessors()? Runtime.getRuntime().availableProcessors() * 2可能是一个好主意

  2. # 2 楼答案

    调整线程池大小取决于要在该池上执行的任务的性质。一般来说,这取决于等待时间和cpu时间之间的比率以及可用cpu的数量

    适用的一般公式为:

    Sizing Threads Pools

    将处理器保持在所需利用率的最佳池大小为:

    Optimal thread-pool sizing

    您可以在Java Concurrency In Practice8.2调整线程池大小部分找到更多信息

  3. # 3 楼答案

    您可以查看Amdahl's law来定义核心的数量。把你的程序当作一个单线程程序,看看你可以在哪里并行化。这可以给您一个N的概念(这里我们可以通过应用程序的线程数来近似计算内核数)

    根据我的经验,确定“最佳”线程数的最佳方法仍然是创建多线程程序,并使用尽可能多的线程数值进行测试,看看哪一个线程输出的性能最好。(另见Optimal number of threads per core

  4. # 4 楼答案

    我想这将取决于你在做什么。您已经暗示一些线程可能正在等待I/O

    corePoolSize是池将保留的线程数,即使空闲。我想您应该设置最大池大小

    上下文切换开销总是存在的,我不认为它会随着线程的增加而增加,因为切换通常是作为常量片实现的(即,时间片的减少不会与可运行线程的数量成反比)

    显然,要实现满负载,您至少需要与内核数量相同的线程,需要多少额外线程取决于线程完成的速度和I/O所需的时间

    一种选择是在具有较大池大小的单独步骤中执行I/O,这样您就可以确保始终有一个已经完成了I/O步骤(CompletableFuture对此很方便)。然后,在下一步中,您将使用一个单独的线程池,该线程池大小与一个线程完成后从上一步输入的内核数相同

    类似这样的内容(未经验证):

    CompletableFuture.supplyAsync(ioTask, ioExecutorWithLargePool)
        .thenAccept(cpuBoundTask, executorWithCpuCoreSizedPool);