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

本文探讨了在Java中使用并行流时结合ForEachOrdered操作的场景与影响。虽然这种组合可能导致并行处理的优势受限,但在需要保持元素顺序的情况下,它是必要的选择。文章通过具体示例说明了这一用法,并讨论了不同情况下的性能考量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Oracle官方文档说:

Note that you may lose the benefits of parallelism if you use

operations like forEachOrdered with parallel streams.

Oracle - Parallelism

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

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

假设我们有这样的东西:

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()

如果你指的是:

stringList.parallelStream().forEachOrdered(action);

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

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。请注意,文档说明可能会丢失,但肯定会丢失 - 您必须进行测量和查看。

感谢'May'和'Will'提到!

我发现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));

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值