我应该尽可能使用并行流吗?

新手上路,请多包涵

使用 Java 8 和 lambda 可以很容易地像流一样遍历集合,使用并行流也同样容易。 文档 中的两个示例,第二个示例使用 parallelStream:

 myShapesCollection.stream()
    .filter(e -> e.getColor() == Color.RED)
    .forEach(e -> System.out.println(e.getName()));

myShapesCollection.parallelStream() // <-- This one uses parallel
    .filter(e -> e.getColor() == Color.RED)
    .forEach(e -> System.out.println(e.getName()));

只要我不关心顺序,使用并行总是有益的吗?人们会认为将工作分配到更多核心上会更快。

还有其他的考虑吗?什么时候应该使用并行流,什么时候应该使用非并行?

(问这个问题是为了引发关于如何以及何时使用并行流的讨论,而不是因为我认为总是使用它们是个好主意。)

原文由 Matsemann 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 353
2 个回答

与顺序流相比,并行流的开销要高得多。协调线程需要花费大量时间。我会默认使用顺序流,只有在以下情况下才考虑并行流

  • 我有大量的项目要处理(或者每个项目的处理都需要时间并且是可并行的)

  • 我首先遇到了性能问题

  • 我还没有在多线程环境中运行该进程(例如:在 Web 容器中,如果我已经有许多请求要并行处理,则在每个请求中添加额外的并行层可能产生的负面影响大于正面影响)

在您的示例中,性能无论如何都将由对 System.out.println() 的同步访问驱动,并且使该过程并行将没有效果,甚至是负面效果。

此外,请记住并行流并不能神奇地解决所有同步问题。如果进程中使用的谓词和函数使用共享资源,则必须确保一切都是线程安全的。特别是,副作用是您并行进行时真正需要担心的事情。

无论如何,测量,不要猜测!只有测量才能告诉您并行性是否值得。

原文由 JB Nizet 发布,翻译遵循 CC BY-SA 3.0 许可协议

Stream API 的设计目的是使编写计算的方式变得容易,这种方式从计算的执行方式中抽象出来,从而使顺序和并行之间的切换变得容易。

然而,仅仅因为它很简单,并不意味着它总是一个 主意,事实上,仅仅因为你可以 .parallel() 一个好主意。

首先,请注意,并行性除了可以在更多内核可用时加快执行速度之外没有其他好处。并行执行总是比顺序执行涉及更多的工作,因为它除了要解决问题之外,还要进行子任务的调度和协调。希望您能够通过跨多个处理器分解工作来更快地找到答案;这是否真的发生取决于很多因素,包括数据集的大小、对每个元素进行的计算量、计算的性质(具体来说,一个元素的处理是否与其他元素的处理相互作用?) ,可用处理器的数量,以及竞争这些处理器的其他任务的数量。

此外,请注意,并行性还经常暴露计算中的不确定性,而这些不确定性通常被顺序实现所隐藏;有时这无关紧要,或者可以通过限制所涉及的操作来缓解(即,归约运算符必须是无状态和关联的。)

实际上,有时并行会加快您的计算速度,有时不会,有时甚至会减慢计算速度。最好先使用顺序执行进行开发,然后在其中应用并行性

(A) 你知道提高性能实际上有好处,并且

(B) 它实际上会带来更高的性能。

(A) 是业务问题,而不是技术问题。如果您是性能专家,通常可以查看代码并确定 (B) ,但明智的做法是测量。 (而且,在您确信 (A) 之前甚至不要打扰;如果代码足够快,最好将您的大脑循环应用到其他地方。)

最简单的并行性能模型是“NQ”模型,其中 N 是元素的数量,而 Q 是每个元素的计算。通常,您需要产品 NQ 超过某个阈值才能开始获得性能优势。 For a low-Q problem like “add up numbers from 1 to N “, you will generally see a breakeven between N=1000 and N=10000 。对于更高 Q 的问题,您会在更低的阈值下看到收支平衡。

但现实是相当复杂的。因此,在您成为专家之前,首先确定顺序处理何时真正让您付出代价,然后衡量并行性是否有帮助。

原文由 Brian Goetz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题