我正在使用Java 8并行流,并且希望以并行流的方式打印元素是某种顺序(例如插入顺序,反向顺序或顺序顺序)。

为此,我尝试了以下代码:

System.out.println("With forEachOrdered:");

listOfIntegers

.parallelStream()

.forEachOrdered(e -> System.out.print(e +""));

System.out.println("");

System.out.println("With Sequential:");

listOfIntegers.parallelStream()

.sequential()

.forEach(e -> System.out.print(e +""));

对于这两者,我得到的输出如下:

With forEachOrdered:

1 2 3 4 5 6 7 8

With Sequential:

1 2 3 4 5 6 7 8

从api文档中,我可以看到:

forEachOrdered -> This is a terminal operation.

sequential -> This is an intermediate operation.

所以我的问题是,哪个更好用?

在哪些情况下,应该优先选择另一种?

listOfIntegers.parallelStream().sequential().forEach()创建一个并行的Stream,然后将其转换为顺序的Stream,因此您最好改用listOfIntegers.stream().forEach(),并首先获得顺序的Stream。

listOfIntegers.parallelStream().forEachOrdered(e -> System.out.print(e +""))在并行的Stream上执行操作,但是保证元素将按Stream的遇到顺序被消耗(如果Stream具有定义的遇到顺序)。但是,它可以在多个线程上执行。

我看不到使用listOfIntegers.parallelStream().sequential()的原因。如果要顺序Stream,为什么要先创建平行的Stream?

因为您可能希望并行执行一些繁重的操作,然后对流重新排序以最终输出

@AdrianShum Im不确定在性能方面的效果如何,因为流是惰性评估的。它不会对所有元素并行执行第一个中间步骤,然后继续其余的中间步骤并在顺序流上进行终端操作。仅当到达终端操作时,它才开始对单个元素执行中间操作,直到它们成为终端操作的输入为止。

确实如此。也许这仅对以下情况有用:我正在编写可在提供的流上使用的util,并且即使用户提供了并行的,我也要确保它是顺序的?

@AdrianShum是的,如果您没有自己创建流,并要求它是顺序的,那么sequential()会很好用。

考虑list.parallelStream().sorted().forEachOrdered(…)作为一个实际的例子,它并行执行大量工作,但执行有序的终端操作。

@Holger,但在示例中您没有将流转换回顺序流

究竟。这是.parallelStream(). … .forEachOrdered(…)和.parallelStream(). … sequential().forEach(…)表现出明显差异的操作示例。如您所说,"流是惰性计算的",因此,如果终端操作由于排序约束而阻塞了工作线程,那么除非您具有像sorted()这样的有状态中间操作,否则您不会获得太多的并行性。

您以某种方式提出了一个令人误解的问题,首先您要询问:

.parallelStream()

.forEachOrdered(...)

这将创建一个并行Stream,但是元素将按顺序使用。如果添加这样的map操作:

.map(...)

.parallelStream()

.forEachOrdered(...)

这将使map的操作非常有限(从并行处理的角度来看),因为线程必须等待遇到顺序中的所有其他元素(由forEachOrdered消耗)。这涉及无状态操作。

另一方面,如果您有状态操作,例如:

.parallelStream()

.map()

.sorted()

.// other operations

由于sorted是有状态的,因此并行处理之前的无状态操作将带来更大的好处。发生这种情况是因为sorted必须从Stream中收集所有元素,并且线程不必"按顺序"遇到元素(在forEachOrdered处)。

对于第二个示例:

listOfIntegers.parallelStream()

.sequential()

.forEach(e -> System.out.print(e +""))

您基本上是说先并联然后再关闭。流由终端操作驱动,因此即使您这样做:

.map...

.filter...

.parallel()

.map...

.sequential

这意味着整个流水线将顺序执行,而不是某个部分是并行的而另一部分则是顺序的。您还依赖于这样一个事实,即forEach会保留顺序并且可能会保留它,但可能会在以后的版本中保留它,这是因为您说过您不关心顺序(首先使用forEach ),则将对元素进行内部改组。

流管线可以顺序执行或并行执行。此执行模式是流的属性。使用初始选择的顺序执行或并行执行来创建流。例如,Collection.stream()创建一个顺序流,而Collection.parallelStream()创建一个并行流。可以通过BaseStream.sequential()或BaseStream.parallel()方法修改执行模式的选择。

因此,无需使用:

listOfIntegers.parallelStream().sequential()

您只能使用:

listOfIntegers.stream()

如果创建parallel stream,则流的元素可能由不同的线程处理。 forEach和forEachOrdered之间的区别在于,forEach将允许以任何顺序处理并行流的任何元素,而forEachOrdered将始终按照其在原始流中出现的顺序来处理并行流的元素。当使用parallelStream()和forEachOrdered时,是一个很好的示例,说明了如何利用多个内核并仍保留输出顺序。请注意,forEachOrdered强制以有序的方式迭代流元素。但是,在forEachOrdered之前链接的任何操作仍将并行发生,因为该流是并行流。

Oracle并没有确切记录在管道中多次更改流执行模式时发生的情况。尚不清楚最后更改是否重要,还是可以并行执行在调用parallel()之后调用的操作是否可以并行执行,而在调用sequential()之后调用的操作是否将依次执行。

"没有记录到当您在管道中多次更改流执行模式时发生的确切情况"。我不同意,它在Stream的类文档中清楚地说明了" Stream管道可以顺序执行或并行执行"

@AnlonBurke请通读最后的内容,Oracle并未对此进行记录。

整个管道可以顺序执行,也可以并行执行。恕我直言,这就是Javadoc所说的话。某些部分不可能是parallel,而另一些部分是sequential(实际上,在Stream API最初开发期间曾尝试过一段时间,但由于过于复杂而已被放弃)。我不明白您对此有何疑问。

java ordered list_关于并行处理:Java 8的forEachOrdered()和sequence()方法之间的区别?...相关推荐

  1. java定义list_我的Java Web之路59 - Java中的泛型

    本系列文章旨在记录和总结自己在Java Web开发之路上的知识点.经验.问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人. 目录 介绍 再谈Java中的类型 为什么需要泛型? J ...

  2. java 方法 函数 区别_Java中的构造函数和方法之间的区别

    Java方法一种方法用于探索对象的行为. 我们可以在方法的前面加上访问修饰符. 方法必须具有返回类型,例如void,任何原始类型(int,char,float等),任何Object类型(Integer ...

  3. java listfiles 使用_Java中list()和listFiles()方法之间的区别

    java.io包的名为File的类表示系统中的文件或目录(路径名).为了获得目录中所有现有文件的列表,此类提供了list()和ListFiles()方法. 它们之间的主要区别是该列表()方法返回一个字 ...

  4. Java中的wait()和sleep()方法之间的区别

    Java中的wait()和sleep()方法 (wait() and sleep() methods in Java) First, we will see how wait() method dif ...

  5. java limit_Java 8 Stream:limit()和skip()之间的区别

    小编典典 您在这里拥有两个流管道. 这些流管道分别由一个源,几个中间操作和一个终端操作组成. 但是中间操作是懒惰的.这意味着除非下游工序需要物料,否则什么也不会发生.如果这样做,则中间操作将完成它所需 ...

  6. java中的for循环里面创建对象和for循环外面创建对象之间的区别

    问题描述: 其实就是我在for循环外面场景对象.想着可以节省内存,可是最终返回list的对象都是最后一个对象对应的数据,代码如下: List<SelectSelfTestReportVo.Con ...

  7. java getmapping(_java - 注释@GetMapping和@RequestMapping(method = RequestMethod.GET)之间的区别...

    @RequestMapping(method=RequestMethod.GET)是一个班级 @RequestMapping(method=RequestMethod.GET)是方法级别 随着spri ...

  8. Java中File的getPath(),getCanonicalPath()和getAbsolutePath()之间的区别

    File API在Java中非常重要,因为它使文件系统可以访问Java程序. 尽管Java的文件API丰富,但是使用它们时仍需要了解许多细节. 关于文件路径的常见查询程序员之一是getPath() , ...

  9. java多核并行计算_谈谈Java任务的并行处理

    前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分利用cpu资源:如果站的更高 ...

最新文章

  1. List中subList方法抛出异常java.util.ConcurrentModificationException原理分析
  2. Pytorch中的错误和bug
  3. 【LeetCode】10. Regular Expression Matching
  4. c++接口与实现的分离
  5. Python代码规范
  6. java中printreader类_java字符流,字符文件输入流FileReader类介绍
  7. 【建行】龙支付新老用户赚200元详细教程
  8. 抗击疫情 融云在行动
  9. 2549. 删除他们! 解题报告
  10. Day 15 正则表达式
  11. OpenLayers 3实践与原理探究3-ol3一个完整的例子
  12. 【PP模块】工艺路线详解(Routing)
  13. iconfont字体图标线上环境加载偶尔乱码问题
  14. shapefile格式(援引)
  15. 【软件测试-实验-7】使用LR进行性能测试
  16. 市场调查与预测试题库【1】
  17. 工程力学(5)—平面任意力系简化与平衡
  18. java设计模式 课后习题参考答案 第 2 章 面向对象设计原则 清华出版社 刘伟
  19. 如何开发一个标准的云原生应用?
  20. 新思路计算机二级考试题库软件,新思路等考通二级Visual Basic

热门文章

  1. oracle 更改实便例名称,大家好,请教在oracle中能否获取update记录 所涉及的字段的名称?如能实现的话,请教相关实现方法。谢谢~...
  2. 厌倦了 VMware,试试更轻量级的虚拟机!
  3. 皮一皮:还以为女神的眼睛特别好看...
  4. Java中的微信支付(1):API V3版本签名详解
  5. 每日一皮:给老板演示刚做好的功能...
  6. 面试:从volatile说到i++的线程安全问题
  7. 这个神器竟然能分分钟将多个 kubeconfig 合并成一个!
  8. 你还在百度这些代码吗?
  9. Spring Doc 生成OPEN API 3文档
  10. 关于程序猿鄙视链,哽咽