Java8采用streamparallelStream迭代的区别

我们都知道在Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

通过查看API能够看到Java8 API为我们提供了Stream和parallelStream两个不同的方法,那么同样是流处理,这两个方法又有什么区别呢?首先我们来看看以下的代码:

public static void main(String[] args) {

List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);

System.out.println("运行结果:");

// stream method

numberList.stream().forEach(number -> {

System.out.print(String.format("%d ",number));

});

System.out.println("\r");

// parallelStream method

numberList.parallelStream().forEach(number -> {

System.out.print(String.format("%d ",number));

});

System.out.println("\r");

// parallelStream method

numberList.parallelStream().forEachOrdered(number -> {

System.out.print(String.format("%d ",number));

});

System.out.println("\r");

}

通过多次运行上述代码,我们可以发现,通过parallelStream方法迭代集合,每次输出的结果都不一样,而通过steam方法或parallelStream方法并以forEachOrdered方式,每次执行输出的结果都是一样的,并且顺序符合集合元素的存放顺序。
那么,为什么会造成这样的结果差异呢,难道parallelStram是采用多线程并行的方式运行?于是,我们进一步修改下我们的代码来验证一下猜测。

public static void main(String[] args) {

System.out.println("运行结果:");

List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);

// stream method

numberList.stream().forEach(number -> {

System.out.println(String.format("Stream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

});

System.out.println("\r");

// parallelStream method

numberList.parallelStream().forEach(number -> {

System.out.println(String.format("ParallelStream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

});

System.out.println("\r");

// parallelStream method

numberList.parallelStream().forEachOrdered(number -> {

System.out.println(String.format("ParallelStream forEach Ordered The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

});

System.out.println("\r");

}

修改后代码运行结果如下:

运行结果:

Stream The Current Thread's ID is 1 and output number 1

Stream The Current Thread's ID is 1 and output number 2

Stream The Current Thread's ID is 1 and output number 3

Stream The Current Thread's ID is 1 and output number 4

Stream The Current Thread's ID is 1 and output number 5

Stream The Current Thread's ID is 1 and output number 6

Stream The Current Thread's ID is 1 and output number 7

Stream The Current Thread's ID is 1 and output number 8

Stream The Current Thread's ID is 1 and output number 9

ParallelStream The Current Thread's ID is 1 and output number 6

ParallelStream The Current Thread's ID is 19 and output number 9

ParallelStream The Current Thread's ID is 18 and output number 1

ParallelStream The Current Thread's ID is 15 and output number 2

ParallelStream The Current Thread's ID is 17 and output number 4

ParallelStream The Current Thread's ID is 14 and output number 8

ParallelStream The Current Thread's ID is 13 and output number 3

ParallelStream The Current Thread's ID is 16 and output number 7

ParallelStream The Current Thread's ID is 1 and output number 5

ParallelStream forEach Ordered The Current Thread's ID is 15 and output number 1

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 2

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 3

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 4

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 5

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 6

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 7

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 8

ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 9

Disconnected from the target VM, address: '127.0.0.1:52976', transport: 'socket'

Process finished with exit code 0

通过上面的运行结果,我们可以看到通过ParallelStream方法迭代的方法,是采用多线程的,可以看过每次输出都是不同的线程ID,而ParallelStream(). forEach Ordered是在多线程的基础上,保证了数据的顺序输出。到此,我们验证了我们的猜测ParallelStream方法是多线程的,而关于线程是否并行的验证,我们需进一步修改下我们的代码,于是有了下面的代码:

public static void main(String[] args) throws InterruptedException {

System.out.println("运行结果:");

List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);

//for

Long forBegin = System.currentTimeMillis();

for(Integer number : numberList){

//System.out.println(String.format("For The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

Thread.sleep(1000);

}

System.out.println(String.format("For execute time cost %d ms",System.currentTimeMillis()-forBegin));

System.out.println("\r");

// stream method

Long streamBegin = System.currentTimeMillis();

numberList.stream().forEach(number -> {

//System.out.println(String.format("Stream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

System.out.println(String.format("Stream execute time cost %d ms",System.currentTimeMillis()-streamBegin));

System.out.println("\r");

// parallelStream method

Long parallelStreamBegin = System.currentTimeMillis();

numberList.parallelStream().forEach(number -> {

//System.out.println(String.format("ParallelStream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

System.out.println(String.format("ParallelStream execute time cost %d ms",System.currentTimeMillis()-parallelStreamBegin));

System.out.println("\r");

// parallelStream method

Long parallelStreamForEachOrderBegin = System.currentTimeMillis();

numberList.parallelStream().forEachOrdered(number -> {

//System.out.println(String.format("ParallelStream forEachOrdered The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

System.out.println(String.format("ParallelStream forEachOrdered execute time cost %d ms",System.currentTimeMillis()-parallelStreamForEachOrderBegin));

System.out.println("\r");

}

这里我们加入了传统的for循环迭代方式,加入一起比较,由于要体现多线程并行的优势,这里我们将每次循环里加入线程休眠1秒钟,运行后的结果如下:

运行结果:

For execute time cost 9032 ms

Stream execute time cost 9079 ms

ParallelStream execute time cost 2011 ms

ParallelStream forEachOrdered execute time cost 9037 ms

通过运行结果,我们可以看到parallelStream().forEach方式耗时最短,而另外其他3种方式运行的耗时都几乎接近。因此,我们可以断定我们的猜测是正确的,parallelStream().forEach是通过多线程并行的方式来执行我们的代码,而parallelStream(). forEachOrdered也是采用多线程,但由于加入了顺序执行约束,故程序是采用多线程同步的方式运行的,最终耗时与for、stream两种单线程执行的耗时接近,但parallelStream(). forEachOrdered由于是多线程,与for、stream两种单线程的方式相比,优势在于很好的利用了CPU多核的资源。感兴趣的同学可以通过以下代码查看CPU的核数,并通过jstack dump出堆栈来查看线程对CPU使用的情况。

System.out.println("系统一共有"+Runtime.getRuntime().availableProcessors()+"个cpu");

来源:Java8采用stream、parallelStream迭代的区别 - 你我一路随行 - 博客园

Java8采用stream、parallelStream迭代的区别相关推荐

  1. 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!

    写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*)  ,那什么是Stream API呢?Java8中 ...

  2. 一文带你了解Java8之Stream

    Java8 Stream流式编程 简介 Java8中stream是用于对集合迭代器的增强,使之能供完成更高效的聚合操作(例如过滤.排序.统计分组等)或者大批量数据操作.此外,stream与lambda ...

  3. Java8的 Stream 流的各种用法

    Java8 的 Stream 流的各种用法 什么是Stream 1. Stream可以由数组或集合创建,对流的操作分为两种 2. Stream的特性 3. Stream可以通过集合数组创建 4. st ...

  4. Java8特性 stream流常用方法

    Java8特性 stream流常用方法 Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方 ...

  5. 玩转Java8的 Stream 之函数式接口

    作者:litesky www.jianshu.com/p/2338cabc59e1 函数式接口是伴随着Stream的诞生而出现的,Java8Stream 作为函数式编程的一种具体实现,开发者无需关注怎 ...

  6. Java8种Stream流相关操作——集合的筛选、归约、分组、聚合

    过滤.筛选   filter skip /*** 过滤 筛选*/@Testpublic void test2(){List<String> list = Arrays.asList(&qu ...

  7. Java8的Stream API使用(笔记)

    个人转载仅作为笔记使用,如有任何问题可以到原文链接探讨,原文连接为:https://www.cnblogs.com/jimoer/p/10995574.html 前言 这次想介绍一下Java Stre ...

  8. Java8的Stream API使用

    前言 这次想介绍一下Java Stream的API使用,最近在做一个新的项目,然后终于可以从老项目的祖传代码坑里跳出来了.项目用公司自己的框架搭建完成后,我就想着把JDK版本也升级一下吧(之前的项目, ...

  9. stream和迭代器的区别

    什么是迭代器? 迭代器,提供一种访问一个集合对象各个元素的途径,同时又不需要暴露该对象的内部细节.java通过提供Iterator和Iterable俩个接口来实现集合类的可迭代性,迭代器主要的用法是: ...

最新文章

  1. C++11 unordered_map详细介绍
  2. oracle idm suite,CorelDRAW Graphics Suite 2018官方英文试用版 离线直接安装 下载地址
  3. ICLR 2020 开源论文 | 隐空间的图神经网络:Geom-GCN
  4. 奇舞团的博客(360前端团队)
  5. lucene 查询示例_高级Lucene查询示例
  6. 血红蛋白判断access程序答案_普渡大学开发智能手机应用程序 帮助评估贫血症情况...
  7. C#文件流传输[类似于QQ][引]
  8. Chrome控制台console的各种用法(方便调试)
  9. Apache Ant 安装教程
  10. java计算机毕业设计化妆品销售网站MyBatis+系统+LW文档+源码+调试部署
  11. 计算机启动到安全模式,电脑正常开机会进入安全模式怎么办
  12. 射灯安装方法图解_射灯如何安装—射灯的安装方法介绍
  13. c语言while(*p *q),C语言经典例题和答案
  14. android发短信!渣本毕业两年经验,终局之战
  15. Python实现相空间重构求关联维数——GP算法、自相关法求时间延迟tau、最近邻算法求嵌入维数m
  16. Nand2Tetris - Week 1
  17. 丰田增设电池生产线,加快丰田电动化进程
  18. 煮咖啡的动态页面演示动画
  19. 环境变量是个啥? 没有勾选Add to Path怎么办?
  20. linux C语言TCP协议实现镜像服务器,并发服务器,文件传输

热门文章

  1. QT的QWriteLocker类的使用
  2. html fmt转换日期格式,js通用时间格式转换函数
  3. 鸿蒙系统是单任务还是多任务,在鸿蒙系统上使用MQTT编程
  4. 使用opencv读取图片错误([ WARN:0@13.701] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\..)
  5. Azkaban实战,Command类型单一job示例,任务中执行外部shell脚本,Command类型多job工作flow,HDFS操作任务,MapReduce任务,HIVE任务
  6. 6.set ff=unix;设置Linux中文件中每行后又尖括号的情况
  7. Oracle_Net_Configuration_Assistant_配置步骤
  8. 因为虚拟机导致的错误
  9. Android中contentProvider的用途
  10. php网站适合优化_php开发大型网站如何优化的方案详解