Java并行流使用与否

VB_*_*VB_ 4 java parallel-processing java-stream

在 Java 中使用并行流而不是执行器服务被认为是不好的做法吗?为什么?

如您所知,将在幕后myList.parallelStream().map(e -> ...)使用。ForkJoinPool.common()因此,如果您同时使用至少两个并行流,您可能会在以下情况下遇到问题:

  1. map函数被阻塞。但有ForkJoinPool.ManagedBlocker可以作为救援。
  2. map函数可能非常占用 CPU 资源,这将导致其他并行流陷入饥饿。有什么办法可以设置RecursiveTasks之间或ForkJoinPools之间的优先级吗?

另一方面,您可以ForkJoinPool根据需要创建任意数量的 s。new ForkJoinPool(4).submit(() -> myList.parallelStream()...在一个 JVM 上使用多个ForkJoinPools 是否被认为是性能明智的?

更新

使用或不使用并行流=使用或不使用ForkJoinPool,对吧?我发现这个这个链接对于回答最后一个问题非常有用

Mar*_*arv 5

没有一种万能的解决方案.parallel()。约书亚·布洛赫 说:

[...] 甚至不要尝试并行化流管道,除非您有充分的理由相信它将保持计算的正确性并提高其速度。不恰当地并行化流的代价可能是程序失败或性能灾难。如果您认为并行性可能是合理的,请确保您的代码在并行运行时保持正确,并在实际条件下进行仔细的性能测量。如果您的代码保持正确,并且这些实验证实了您对性能提高的怀疑,那么只有这样才能在生产代码中并行化流。

- 《Effective Java》第 3 版,第 225 页,第 28 条:使流并行时要小心

他建议您在现实条件下进行彻底的基准测试,并根据具体情况做出决定。此外,使用不仅会.parallel()导致性能不佳,还会导致安全故障:

安全故障可能是由于并行化使用映射器、过滤器和其他程序员提供的函数对象而无法遵守其规范的管道而导致的。

- 《Effective Java》第 3 版,第 224 页,第 28 条:使流并行时要小心

要回答您的问题,这并不被认为是不好的做法,但是您在使用时应该极其谨慎.parallel(),而不是盲目地将其应用到代码库中的每个流上。