当同一流管道中使用的终端操作不符合遭遇顺序时,中间操作是否会遇到订单?

问题描述 投票:2回答:2

如果我在流管道中使用map操作与forEach()终端操作(不遵守其顺序或并行流的顺序或顺序流的遭遇顺序),将映射尊重列表的遭遇顺序在顺序或并行流的情况下?

List<Integer> = Arrays.asList(1,2,3,4,5)
someList.stream().map(i -> i*2).forEach(System.out::println) // this is sequential stream
someList.parallelStream().map(i -> i*2).forEach(System.out::println) // this is parallel stream

如果是,那么在这篇文章https://stackoverflow.com/a/47337690/5527839中,提到地图操作将并行执行。如果维护订单,那么在使用并行流时如何使性能更好。使用并行流有什么意义?

java java-8 java-stream
2个回答
2
投票

如果维护订单,那么在使用并行流时如何使性能更好。使用并行流有什么意义? (是的,你仍然可以获得性能,但不是预期的水平)

即使你使用forEachOrdered()parallelStream中间操作map将由并发线程执行,但在终端操作中orEachOrdered使它们按顺序处理。尝试以下代码,您将在map操作中看到并行性

List<Integer> someList = Arrays.asList(1,2,3,4,5);
            someList.stream().map(i -> {
                System.out.println(Thread.currentThread().getName()+" Normal Stream : "+i);
                return i*2;
            }).forEach(System.out::println); // this is sequential stream

            System.out.println("this is parallel stream");

            someList.parallelStream().map(i -> {
                System.out.println(Thread.currentThread().getName()+" Parallel Stream : "+i);
                return i*2;
            }).forEachOrdered(System.out::println); // this is parallel stream

将映射荣誉遭遇命令?订购与中间操作有关的任何方式?

如果是parallelstream地图将不会遇到任何顺序,如果是普通流然后地图会遇到顺序,它完全取决于流不中间操作


1
投票

虽然许多中间操作确实保留了排序而不必明确指定该期望,但我总是倾向于假设流经java流API的数据不能保证在每个场景中最终排序,即使给定相同的代码。

当必须保留元素的顺序时,将终端操作指定为有序操作就足够了,数据在出现时将按顺序排列。在你的情况下,我相信你一直在寻找

.forEachOrdered()

如果维护订单,那么在使用并行流时如何使性能更好。使用并行流有什么意义?

我听到了很多这方面的意见。我相信如果你在管道内进行非常少量的处理,你应该只使用并行流,否则管理并行流的开销在大多数情况下会比串行流降低性能。如果你正在进行一些密集处理,即使被指示保留顺序,并行仍然肯定比串行工作更快,因为,毕竟,正在处理的数据以任何一种方式存储在堆中,并且指向该数据的指针是有序的和从管道末端传出。所有流需要进行排序都是按照遇到的顺序将指针输出,但它可以并行处理数据,只是等待队列前面的数据尚未完成。

我确信这有点过于简单化了,因为有些情况下有序流需要从一个元素到下一个元素共享数据(例如收集器)但是基本概念是有效的,因为即使在这种情况下并行流能够一次处理至少两个数据。

© www.soinside.com 2019 - 2024. All rights reserved.