parallelStream vs stream.parallel

Nic*_*ark 23 java java-8

我一直很好奇Collections.parallelStream()和之间的区别Collections.stream().parallel().根据Javadocs,parallelStream()尝试返回并行流,而stream().parallel()返回并行流.通过对我自己的一些测试,我发现没有差异.这两种方法的区别在哪里?一个实现比另一个更有效吗?谢谢.

Eug*_*ene 17

即使他们采取同样的时刻,是有区别的-至少他们的文档中,你正确指出的; 据我所知,未来可能会被利用.

目前,该parallelStream方法在Collection界面中定义为:

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}
Run Code Online (Sandbox Code Playgroud)

作为一种默认方法,它可以在实现中被覆盖(这就是Collections内部类实际上做的事情).

这暗示即使默认方法返回并行Stream,也可能有覆盖此方法的Collections返回a non-parallel Stream.这就是文档可能是这样的原因.

同时,即使parallelStream收益连续流-它仍然是一个Stream; 然后你可以轻松地打电话parallel给它:

  Collections.some()
       .parallelStream() // actually sequential
       .parallel() // force it to be parallel
Run Code Online (Sandbox Code Playgroud)

至少对我来说这看起来很怪异.

似乎文档应该以某种方式说明在调用parallelStream之后应该没有理由parallel再次强制调用- 因为它可能对处理无用甚至不好.

编辑

对于阅读此内容的任何人 - 请阅读Holger的评论; 它涵盖的范围超出了我在这个答案中的说法.

  • 好吧,一个空的集合永远不会从并行处理中受益,但是,因为无论如何都不能保证线程的数量,所以仍然让 `isParallel()` 返回 `true` 没有坏处。同样,在没有 `flatMap` 操作的单例集合上的流永远不会使用第二个线程,但 `isParallel()` 返回 `true` 没有坏处。这也适用于其底层拆分器在 `trySplit` 中返回 `null` 的所有流;没有像 `sorted` 或 `flatMap` 这样的东西,你是否调用 `.parallel()` 都没有关系;它不会有任何影响。 (3认同)
  • 很难想象这样一种场景,流 *source* 拒绝对流进行并行处理,而不知道将链接哪些实际操作是合理的。也许,如果它正在滚动自己的 `Stream` API 实现,但是,它完全控制调用 `.parallel()` 时发生的事情...... (2认同)
  • 只是想它结束,如果你有一个不支持任何并行处理的源,仍然没有理由为什么`thatSource .parallelStream() .sorted()。应该禁止 otherOps()` 使用并行处理,一旦内部使用的数组被填充,那么处理就完全与源分离了。我有一种感觉,这句话源于源和流实现之间的交互仍在进行中的时候。 (2认同)
  • @Holger 有时我实际上并没有得到你的答案,但肯定会尝试去修改它们......通过内部数组,你的意思是这里的`sorted`操作会将元素从`Spliterator`复制到`Sink`(数组或`ArrayList`)对吗?抱歉这么晚才提出来 (2认同)
  • 是的,确切地说,`sorted()` 使用的临时存储,无论是否为数组,都独立于源集合,因此可以并行处理,即使源试图拒绝它。同样,如果拆分器的`trySplit` 方法返回`null`,则Stream 实现*可能* 转向像`AbstractSpliterator.trySplit` 那样的缓冲策略。实际上,如果 Stream 这样做而不是 `AbstractSpliterator` 会更有意义...... (2认同)

Joe*_*e C 6

Collections.parallelStream()和之间没有区别Collections.stream().parallel().它们都会将流划分为底层分裂器允许的范围,并且它们都将使用默认的ForkJoinPool运行(除非已在另一个内部运行).