ForkJoinPool的健康和调优

6
我正在调查使用ForkJoinPool的应用程序中的性能问题。我们一直在使用Dynatrace,发现有一些阻塞操作持续时间过长的迹象。我无法在FJP文档或其他地方找到足够的信息来配置和监视我们的ForkJoinPools。
1.在ForkJoinPools的背景下,什么是并行性,并且对于不同的线程池(阻塞/非阻塞),选择哪些值的指南/最佳实践是什么?
2.如何监视和调整我的ForkJoinPool?我们正在使用ForkJoinPool.toString(),它提供了一些计数器,但我不能在javadoc中找到足够的信息来使用这些统计数据进行调整。getStealCount()被描述为“...应该足够高,以使线程保持繁忙,但足够低,以避免跨线程的开销和争用”,这并没有真正帮助。
toString()的示例:
[Running, parallelism = 48, size = 47, active = 0, running = 0, steals
= 33195, tasks = 0, submissions = 0]

2
你提到有些操作太长了,能否提供一些关于这些部分的信息?也许改进这些部分也可以帮助解决问题。 - prmottajr
1
API正在并行地从其他服务中获取信息。来自某个服务的响应将会根据第一个响应调用更多的并行调用。因此,这里有很多CompletableFuture的链式调用。到目前为止,使用不同的线程池进行io/计算,并将并行度增加到2 x处理器已经产生了积极的影响,但并行级别有点猜测。因此,需要了解ForkJoinPool报告的统计数据。 - oyvind.s
你能分享你执行的代码吗?或者至少提供一个最小可执行文件以帮助分析吗? - prmottajr
1个回答

4
据我所知,没有办法调整这个“框架”。配置仅限于并行性、线程工厂、异常处理和备用线程(请参见下面的并行性)。
我在2011年写了一篇关于F/J代码的批判。我多次升级了这篇批评,不再浪费时间这样做。
偷窃计数完全没有价值。
没有每个线程的统计数据,因此,活动、运行、任务等都无法让你了解框架内部发生了什么。大多数这些“监视器”是在最初的Java7推出几年后添加的。例如,对于每个线程,知道总共处理了多少compute()方法、总等待时间等,可以让你了解每个线程的表现。然而,由于框架添加/删除线程(请参见下面的并行性),这永远不可能发生。对任何这些监视器的总体计数并没有告诉你任何有用的信息。
当然,join()仍然存在严重的阻塞问题。如果你可以使用CountedCompleter类,那么你会更好。

并行意味着初始线程的数量。当线程阻塞达到最大值时(java.util.concurrent.ForkJoinPool.common.maximumSpares,这可能在Java8中不可用,除非它被后移),框架会超出此数目。根据内部规则,框架添加/删除线程(您需要自己查看代码,因为它取决于版本)。另请参见接口ForkJoinPool.ManagedBlocker及其支持代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接