如何在java中的并行程序中获得理想的线程数?

时间:2017-02-03 02:22:12

标签: java multithreading performance spring-batch

我需要在批处理程序中获得理想的线程数,该程序在支持并行模式的批处理框架中运行,如Spring Batch中的并行步骤。

据我所知,执行程序步骤的线程太多并不好,可能会对程序的性能产生负面影响。一些因素可能导致性能下降(上下文切换,使用共享资源时的竞争条件(锁定,同步......)......(还有其他因素吗?))。

当然,获得理想线程数的最佳方法是让我有实际的程序测试来调整程序的线程数。但在我的情况下,进行实际测试并不容易,因为测试需要很多东西(人员,测试计划,测试数据等等),这对我来说现在很难准备。所以,在进行实际测试之前,我想知道如何尽可能地获得我的程序中可猜测的理想线程数。 我应该考虑什么来获得我的程序的理想线程数(步数)? CPU核心数?我的程序运行的机器上的进程数?数据库连接数? 在这样的情况下,有没有合理的方法,比如公式?

3 个答案:

答案 0 :(得分:15)

最重要的考虑因素是您的应用程序/计算是受CPU限制还是IO限制。

  • 如果它是IO绑定的(单个线程花费大部分时间等待外部资源,如数据库连接,文件系统或其他外部数据源),那么您可以分配(多个)多个线程而不是数量可用的处理器 - 当然有多少还取决于外部资源的扩展程度 - 本地文件系统,可能不是那么多。
  • 如果它(大部分)是CPU绑定的,那么稍微超过数量 可用的处理器可能是最好的。

答案 1 :(得分:2)

  

我应该考虑什么来获得我的程序的理想线程数(步数)? CPU核心数?我的程序运行的机器上的进程数?数据库连接数?在这样的情况下,有没有合理的方法,比如公式?

如果没有对线程实际代码的大量了解,这将非常困难。正如@Erwin所提到的,IO与CPU绑定操作是所需的知识的关键部分,您可以确定即使应用程序的线程化也会有任何改进。即使您确实找到了特定硬件的最佳位置,也可以在另一台服务器(或虚拟云节点的不同实例)上启动,并查看截然不同的性能数据。

要考虑的一件事是在运行时更改线程数。 ThreadPoolExecutor.setCorePoolSize(...)旨在在线程池运行后调用。您可以手动公开一些JMX挂钩来为您执行此操作。

您还可以允许应用程序在运行时监视应用程序或系统CPU使用情况,并根据该反馈调整值。您还可以保留AtomicLong吞吐量计数器,并在运行时上下调用线程,以尝试最大化吞吐量。然而,做到这一点可能会很棘手。

我通常会尝试:

  • 最佳猜测一个主题号
  • 检测您的应用程序,以便确定不同线程数的影响
  • 允许它在运行时通过JMX进行调整,这样我就可以看到影响
  • 确保线程数是可配置的(可能通过系统属性),因此您不必重新发布以尝试不同的线程号

答案 2 :(得分:1)

一般公式:

线程数<=(内核数)/ 1-阻塞因子

其中0 <=阻塞因子<1

机器核心数:Runtime.getRuntime().availableProcessors()

可以并行化的线程数,您可以通过打印以下代码获得:

ForkJoinPool.commonPool()

数字并行度是您计算机的核心数量-1。因为那是主线程。

Source link

时间:1:09:00