关于java:使用带有并行流的forEachOrdered的好处

Benefit of using forEachOrdered with Parallel streams

Oracle官方文档说:

Note that you may lose the benefits of parallelism if you use
operations like forEachOrdered with parallel streams.
Oracle - Parallelism

如果我们失去并行性,为什么有人会使用forEachOrdered并行流?


根据具体情况,使用ForEachOrdered不会失去并行性的所有好处。

假设我们有这样的东西:

1
2
stringList.parallelStream().map(String::toUpperCase)
                           .forEachOrdered(System.out::println);

在这种情况下,我们可以保证ForEachOrdered终端操作将在遭遇顺序中以大写形式打印出字符串,但我们不应该假设这些元素将按照它们被选中的顺序传递给map中间操作用于处理。 map操作将由多个线程同时执行。所以人们仍然可以从并行性中受益,但这只是我们没有充分发挥并行性的潜力。总而言之,我们应该在重要的时候使用ForEachOrdered来按流的遭遇顺序执行操作。

编辑以下评论:

What happens when you skip map operation? I am more interested in
forEachOrdered right after parallelStream()

如果你指的是:

1
 stringList.parallelStream().forEachOrdered(action);

做这样的事情没有任何好处,我怀疑这是设计师在决定创建方法时的想法。在这种情况下,做更有意义的事情:

1
stringList.stream().forEach(action);

扩展你的问题"如果我们失去并行性,为什么有人会使用forEachOrdered和并行流",比如说你想对每个元素执行一个关于流遇到顺序的动作;在这种情况下,您需要使用ForEachOrdered,因为forEach终端操作在并行使用时是非确定性的,因此有一个版本用于顺序流,一个版本专门用于并行流。


我真的不明白这里的问题。为什么?因为你别无选择 - 你有这么多的数据,并行流将帮助你(这仍然需要证明);但是你仍然需要保留订单 - 因此ForEachOrdered。请注意,文档说明可能会丢失,但肯定会丢失 - 您必须进行测量和查看。


我发现stream().forEachOrdered()比其并行对应物快约50%。此外,并行的一个使用来自公共fork-join线程池的至少一个线程,这对于在JVM中运行的其他并行流来说是少一个线程。


public static void main(String[] args) {
long start = System.currentTimeMillis();
IntStream.range(0,10000000).parallel().forEachOrdered(i -> {
//System.out.println(Thread.currentThread().getName());
int p = 1 * 1 ;
});
System.out.println((System.currentTimeMillis() - start));
}