【问题标题】:Java parallel stream use or not to useJava并行流使用或不使用
【发布时间】:2018-01-27 00:53:24
【问题描述】:

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

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

  1. map 函数被阻塞。但是有 ForkJoinPool.ManagedBlocker 作为救援。
  2. map 函数可能会占用大量 CPU,这将导致其他并行流饿死。 有没有办法在RecursiveTasks 或ForkJoinPools 之间设置优先级?

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

更新

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

【问题讨论】:

标签: java parallel-processing java-stream


【解决方案1】:

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

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

-Effective Java 3rd Edition,第 225 页,第 28 条:在使流并行时要小心

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

安全故障可能是由于并行化使用 映射器、过滤器和其他程序员提供的未能遵守的函数对象 符合他们的规格。

-Effective Java 3rd Edition,第 224 页,第 28 项:使流并行时要小心

要回答您的问题,这并不是不好的做法,但在使用 .parallel() 时应格外小心,不要盲目地将其应用于代码库中的每个流。

【讨论】:

  • 是的,但是除了所有这些陈述之外的原因是什么?这些建议非常笼统,就像没有人知道如何更好,让我们每次都进行基准测试。此外,我的问题是关于并行流与执行器服务
【解决方案2】:

这是一个非常有趣的演讲,分享了一些关于“何时考虑使用并行流?”这个问题的智慧,由 Brian Goetz 本人分享。 他接替了本次研讨会的第二部分: https://www.youtube.com/watch?v=2nup6Oizpcw&t=25m43s

Brian Goetz 是 Oracle 的 Java 语言架构师,并且是 JSR-335 规范引导(Java 的 Lambda 表达式) 编程语言。)他是最畅销的 Java 的作者 Concurrency in Practice,以及超过 75 篇关于 Java 的文章 开发,并从 Jimmy Carter 开始对编程着迷 是总统。

【讨论】:

    猜你喜欢
    • 2016-07-23
    • 2016-07-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多