短篇小说
与软件工程中的大多数事情一样,答案是:“这取决于”。
使用公共池的优点
如果你看this精彩文章:
根据 Oracle 的文档,使用预定义的公共池可以减少资源消耗,因为这不鼓励为每个任务创建单独的线程池。
和
使用fork/join框架可以加快大型任务的处理速度,
但要实现这一结果,应遵循一些准则:
- 使用尽可能少的线程池——在大多数情况下,最好的决定
是每个应用程序或系统使用一个线程池
- 使用默认值
公共线程池,如果不需要特定的调整
- 使用合理的阈值将 ForkJoingTask 拆分为子任务
- 避免 ForkJoingTasks 中的任何阻塞
使用专用池的优点
不过,也有一些论据反对遵循这种方法:
复杂应用程序的专用池
在复杂的应用程序中为每个逻辑工作单元设置一个专用池有时是首选方法。想象一个应用程序:
- 参加很多活动并将它们分组(可以并行完成)
- 然后工作人员完成工作(也可以并行完成)
- 最后,一些清理工作人员会进行一些清理(也可以并行完成)。
因此,您的应用程序有 3 个逻辑工作组,每个工作组可能对并行性有自己的要求。 (请记住,此池的并行度设置为 something fairly low on most 机器)
最好不要踩到对方的脚趾,对吧?请注意,这可以扩展到某个级别,建议为每个这些工作单元使用单独的微服务,但如果由于某种原因您还没有在那里,那么每个逻辑工作单元的专用 forkJoinPool 是 不错的主意。
其他库
如果您的应用程序代码只有一个地方需要并行性,那么您不能保证某些开发人员不会提取同样依赖于通用 ForkJoinPool 的某些 3 方依赖项,并且您仍然有两个地方需要这个池的地方。对于您的用例来说,这可能没问题,也可能不是,尤其是当您的默认池的并行度为 4 或更低时。
想象一下当您的应用程序关键代码(例如事件处理或将数据保存到数据库)必须与一些导出日志的库竞争公共池时的情况与一些日志接收器并行。
专用的 ForkJoinPool 使日志记录更整洁
此外,常见的 forkJoinPool 有一个非描述性的命名,因此如果您正在调试或查看日志,您可能需要筛选大量的
ForkJoinPool.commonPool-worker-xx
在上述情况下,将其与:
ForkJoinPool.grouping-worker-xx
ForkJoinPool.payload-handler-worker-xx
ForkJoinPool.cleanup-worker
因此,您可以看到在为每个逻辑工作组使用专用 ForkJoinPool 时,记录清洁度有一些好处。
TL;DR
使用通用的 ForkJoinPool 内存影响较小,资源和线程创建较少,垃圾收集需求较低。但是,如上所述,这种方法对于某些用例可能不够用。
在您的应用程序中为每个逻辑工作单元使用专用的 ForkJoinPool 提供更整洁的日志记录,在并行度较低时使用(即内核不多)并不是一个坏主意),以及当您想要避免应用程序的逻辑不同部分之间的线程争用时。然而,这以更高的 CPU 利用率、更高的内存开销和更多的线程创建为代价。