当我遇到这个
ForkJoinPool
的构造函数时,我正在研究有关Fork/Join框架的oracle文档:ForkJoinPool(int parallelism)
。文档说这是“并行级别,默认情况下等于可用处理器的数量”。谁能告诉我如何使用它来提高程序的速度和效率?
本质上,并行度设置告诉
默认设置通常是最佳的,但是假设您有一个与
ForkJoinPool
分开的工作线程,那么您可能会发现将工作线程数设置为处理器数 - 1 比使用所有处理器更好。一般来说,提高特定程序速度和效率的唯一方法是使用不同的设置进行配置。答案是,它用于“调整线程池大小”。 那么让我们看看 Java 平台创建者是怎么说的。
“线程池的理想大小取决于将提交的任务类型和部署系统的特征。线程池大小很少应该被硬编码;相反,池大小应该由配置机制提供或计算通过咨询 Runtime.availableProcessors 动态地进行。
调整线程池的大小并不是一门精确的科学,但幸运的是,您只需要避免“太大”和“太小”的极端即可。如果线程池太大,则线程会争夺稀缺的CPU和内存资源,导致更高的内存使用率和可能的资源耗尽。如果它太小,吞吐量就会受到影响,因为尽管有可用的工作,但处理器仍处于未使用状态。
要正确调整线程池的大小,您需要了解您的计算环境、资源预算和任务的性质。部署系统有多少个处理器?多少内存?任务主要执行计算、I/O 还是某种组合?它们是否需要稀缺资源,例如 JDBC 连接?如果您有不同类别的任务且行为截然不同,请考虑使用多个线程池,以便每个线程池都可以根据其工作负载进行调整。
对于计算密集型任务,Ncpu 处理器系统通常通过 Ncpu +1 线程的线程池实现最佳利用率。 (即使是计算密集型线程偶尔也会因其他原因出现页面错误或暂停,因此“额外”的可运行线程可以防止 CPU 周期在发生这种情况时闲置。)对于还包含 I/O 或其他阻塞操作的任务,您可以想要一个更大的池,因为并非所有线程都可以随时调度。为了正确调整池的大小,您必须估计任务的等待时间与计算时间的比率;该估计不需要精确,可以通过分析或检测来获得。或者,可以通过在基准负载下使用几种不同的池大小运行应用程序并观察 CPU 利用率水平来调整线程池的大小。
给出这些定义:
int N_CPUS = Runtime.getRuntime().availableProcessors();
当然,CPU 周期并不是您可能想要使用线程池管理的唯一资源。其他可能影响大小限制的资源包括内存、文件句柄、套接字句柄和数据库连接。计算这些类型资源的池大小限制更容易:只需将每个任务需要的资源量相加,然后将其除以可用总量即可。结果将是池大小的上限。
当任务需要数据库连接等池化资源时,线程池大小和资源池大小相互影响。如果每个任务都需要一个连接,则线程池的有效大小受连接池大小的限制。同样,当连接的唯一消费者是池任务时,连接池的有效大小受到线程池大小的限制。”
总结
正如您从文档中了解到的,它的默认值是 Runtime.availableProcessors()