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终端操作在并行使用时是非确定性的,因此有一个版本用于顺序流,一个版本专门用于并行流。
-
跳过地图操作会发生什么?我对parallelStream()之后的forOachOrdered更感兴趣
-
@Kaunteya没有太大变化,无论如何溪流都是由终端操作驱动的
-
如果你指的是像stringList.parallelStream().forEachOrdered(action);这样的东西并回答你的问题如果我们失去并行性,为什么有人会使用forEachOrdered并行流,这是因为你别无选择。假设您希望针对流遇到顺序对每个元素执行操作,那么您将需要使用它,因为并行使用时forEach终端操作是非确定性的。
-
一个更有趣的例子是stringList.parallelStream().sorted().forEachOrdered(action)
-
@Holger ......让这个有趣的是sorted的添加?我不知道是什么让这个更有趣:|
-
@Eugene:对于有序流,并行工作者必须等待消费者,直到所有遇到命令的元素都被消耗掉,因此map步骤(以及所有其他紧接的无状态中间操作)的并行处理是非常有限。相反,sorted步骤将并行地执行整个流的排序,而不受后续forEachOrdered的约束的影响。这也适用于排序之前的中间步骤,因为它们也可以无限制地同时运行。
-
@Aominè你认为stringList.parallelStream().forEachOrdered(action);不仅提供了超过stream().forEachOrdered(action)的任何好处,而且还在常见的fork-join线程池中的线程上实现了同样的功能吗?
-
@Kaunteya可以做stream().forEachOrdered(action)但理想情况下做stream().forEach(action)要好得多,因为前者用于并行流。我可能错了,但我怀疑stringList.parallelStream().forEachOrdered(action);实际上会启动多个线程。 java doc声明parallelStream()以此集合作为源返回可能并行的Stream。这个方法允许返回顺序流。所以我认为stringList.parallelStream().forEachOrdered(action);只会在一个线程中执行。
-
也许,@ Holger可以启发我们一些关于你的问题,因为我有兴趣知道我所说的是否有效。
-
@Aominè如果您有兴趣,请查看我发布的答案。
我真的不明白这里的问题。为什么?因为你别无选择 - 你有这么多的数据,并行流将帮助你(这仍然需要证明);但是你仍然需要保留订单 - 因此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));
}