Java ForkJoinPool 的并行度是多少?

问题描述 投票:0回答:2

当我遇到这个

ForkJoinPool
的构造函数时,我正在研究有关Fork/Join框架的oracle文档:
ForkJoinPool(int parallelism)
。文档说这是“并行级别,默认情况下等于可用处理器的数量”。谁能告诉我如何使用它来提高程序的速度和效率?

本质上,并行度设置告诉
java fork-join
2个回答
8
投票
要使用多少个工作线程。

默认设置通常是最佳的,但是假设您有一个与 
ForkJoinPool

分开的工作线程,那么您可能会发现将工作线程数设置为处理器数 - 1 比使用所有处理器更好。一般来说,提高特定程序速度和效率的唯一方法是使用不同的设置进行配置。


答案是,它用于“调整线程池大小”。 那么让我们看看 Java 平台创建者是怎么说的。

0
投票
引用 Brian Goetz 的书《Concurrency in Practice》,第 8 章,8.2。调整线程池大小

“线程池的理想大小取决于将提交的任务类型和部署系统的特征。线程池大小很少应该被硬编码;相反,池大小应该由配置机制提供或计算通过咨询 Runtime.availableProcessors 动态地进行。

调整线程池的大小并不是一门精确的科学,但幸运的是,您只需要避免“太大”和“太小”的极端即可。如果线程池太大,则线程会争夺稀缺的CPU和内存资源,导致更高的内存使用率和可能的资源耗尽。如果它太小,吞吐量就会受到影响,因为尽管有可用的工作,但处理器仍处于未使用状态。

要正确调整线程池的大小,您需要了解您的计算环境、资源预算和任务的性质。部署系统有多少个处理器?多少内存?任务主要执行计算、I/O 还是某种组合?它们是否需要稀缺资源,例如 JDBC 连接?如果您有不同类别的任务且行为截然不同,请考虑使用多个线程池,以便每个线程池都可以根据其工作负载进行调整。

对于计算密集型任务,Ncpu 处理器系统通常通过 Ncpu +1 线程的线程池实现最佳利用率。 (即使是计算密集型线程偶尔也会因其他原因出现页面错误或暂停,因此“额外”的可运行线程可以防止 CPU 周期在发生这种情况时闲置。)对于还包含 I/O 或其他阻塞操作的任务,您可以想要一个更大的池,因为并非所有线程都可以随时调度。为了正确调整池的大小,您必须估计任务的等待时间与计算时间的比率;该估计不需要精确,可以通过分析或检测来获得。或者,可以通过在基准负载下使用几种不同的池大小运行应用程序并观察 CPU 利用率水平来调整线程池的大小。

给出这些定义:

使处理器保持所需利用率的最佳池大小是:

您可以使用 Runtime 确定 CPU 数量:

int N_CPUS = Runtime.getRuntime().availableProcessors();

当然,CPU 周期并不是您可能想要使用线程池管理的唯一资源。其他可能影响大小限制的资源包括内存、文件句柄、套接字句柄和数据库连接。计算这些类型资源的池大小限制更容易:只需将每个任务需要的资源量相加,然后将其除以可用总量即可。结果将是池大小的上限。

当任务需要数据库连接等池化资源时,线程池大小和资源池大小相互影响。如果每个任务都需要一个连接,则线程池的有效大小受连接池大小的限制。同样,当连接的唯一消费者是池任务时,连接池的有效大小受到线程池大小的限制。”

总结

正如您从文档中了解到的,它的默认值是 Runtime.availableProcessors()

    我不同意 Alex 的回答,书中说“你有一个与 ForkJoinPool 分开的工作线程,那么你可能会发现将工作线程的数量设置为处理器的数量 - 1 比使用所有处理器更好”布莱恩·戈茨 (Brian Goetz) 说相反。
  1. 正如您从书中内容中看到的那样,有必要不要输入太小或太大的值,并将其保留在可用处理器附近的某个位置
  2. 另一个重要方面是了解任务的性质,以有效地利用该价值
© www.soinside.com 2019 - 2024. All rights reserved.