Java 1.8中并行和顺序流的区别

时间:2017-12-24 13:53:43

标签: java lambda java-8 functional-programming java-stream

顺序流和并行流在Java 1.8 方面的功能差异是什么,以及输出将如何受到影响?

在哪种情况下选择并行或顺序流?

Java中顺序和并行流的处理方法差异是什么?!!

我已尝试使用以下代码段来测试少量数据,但输出没有任何异常差异。!!

ArrayList<Integer> arrayList = new ArrayList<>();
for(int i = 1; i <= 100;i++) arrayList.add(i);

arrayList.stream().filter(l -> l > 90).forEach(l -> System.out.println(l));

arrayList.parallelStream().filter(l -> l > 90).forEach(l -> System.out.println(l));

5 个答案:

答案 0 :(得分:4)

由于您正在创建并行流,因此可以通过不同的线程处理流的元素。并行流允许多个线程独立地处理流的各个部分。您使用parallelStream()的代码说明了如何利用多个核心。

在100个元素上使用parallelStream()时,您看不出有什么大不同。你需要更多的东西。

谈到排序,使用forEachforEachOrdered还有两种方法可以实现这一目标。它们之间的区别在于forEach将允许以任何顺序处理并行流的任何元素,而forEachOrdered将始终按照它们在原始流中的出现顺序处理并行流的元素。因此,在这种情况下,如果您原样保留forEach,则无法保证订单。

答案 1 :(得分:3)

对于您的具体示例,您很幸运没有看到任何差异(将循环添加到101,以便元素在线程中分布更差并查看差异){{ 1}}记录为:

  

此操作的行为明确是不确定的

因此,至少对于并行处理,将不会有任何顺序 - 至少在某种意义上你不能依赖它。如果您需要, 保证订单forEach

选择forEachOrderedparallel并非易事 - 您应该衡量,Brian's advices are the best to read here

答案 2 :(得分:2)

通常,并行流基本上是一个流,它将其元素分成多个块,使用不同的线程处理每个块。因此,您可以在多核处理器的所有核心上自动对给定操作的工作负载进行分区,并使所有核心处理器保持同等忙碌状态。

然而,重要的是要注意,仅通过调用parallelStream()并不一定使流并行,事实上,调用此方法甚至可能返回顺序流而不是并行流。

如java doc中所述:

  

error message showing on the cmd

     

以此集合作为源返回可能并行的Stream。   此方法允许返回顺序流

因此,我们可以得出结论库,以确定它是否适合使用多个线程。 在大多数情况下,当需要处理大量数据时会出现这种情况。

在您的情况下,ArrayList中似乎只有 100 元素,因此您是否使用parallelStream()没有区别。

最后,但并非最不重要的是,我总是使用顺序流以顺序方式处理数据,除非有大量数据需要处理或者您需要处理;重新遇到使用顺序流处理数据的性能问题,在这种情况下,您可以切换到 parallelStream

答案 3 :(得分:1)

Stream的文档声明parallel是流的属性,但不会增加很多关于实现规范的内容。

不同之处在于对流执行声明性操作。在大多数情况下,除非结果很重要,否则差异不会显示出来。

可能会在您调用的forEach终端流方法中找到差异的最佳解释。 Stream.forEach的文档规定:

  

此操作的行为明确是不确定的。 对于并行流管道,此操作无法保证   尊重流的遭遇顺序,因为这样做会牺牲   并行的好处。对于任何给定元素,动作可以是   在任何时间和任何线程中执行库   选即可。如果操作访问共享状态,则由其负责   提供所需的同步。

换句话说,顺序流以牺牲并发性为代价来保证顺序。这只是其中之一。

答案 4 :(得分:-1)

  

顺序和并行之间的功能区别是什么   根据Java的流

不应该有任何误解:并行处理与并发处理不同。

  

在哪种情况下选择并行或顺序流?

使用并行流可能有用也可能没有用,它实际上取决于您使用的是什么。有时它们更快,有时甚至更慢。

有一种说法如果你能做某事并不意味着你应该这样做。