流API--使用并行流
这篇博客一起来研究下使用并行流。借组多核处理器并行执行代码可以显著提高性能,但是并行编程可能十分复杂且容易出错,流API提供的好处之一是能够轻松可靠的并行执行一些操作。请求并行处理流,首先要获得一个并行流。
获取一个并行流有2个方法:
1,Collection定义的parallelStream()方法
2,对顺序流调用parallel()方法。
一下代码演示如果获取一个并行流:
public static void main(String[] args) throws Exception
{
List<Integer> list = new ArrayList<>(4);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//直接从集合中获取并行流
Stream<Integer> parallelStream = list.parallelStream();
//先获取一个顺序流,然后在顺序流的基础上获取一个并行流
Stream<Integer> stream = list.stream();
Stream<Integer> parallel = stream.parallel(); //Stream中有一个方法可以判断当前的流是不是并行流,一下代码输出全是true,也就是全部都是并行流
System.out.println(parallelStream.isParallel());
System.out.println(stream.isParallel());
System.out.println(parallel.isParallel());
}
获取并行流,有2点要注意,
1,对于并行流,只有在环境支持的情况下才可以实现并行处理
2,在一个顺序流的基础上调用parallel()方法,原来的顺序流也就变成了并行流了。如果调用该方法的流原来已经就是一个并行流了,那么就直接返回该调用流。
当然我们也可以将一个并行流转换成一个顺序流:在并行流上调用sequential()就可以啦。
public static void main(String[] args) throws Exception
{
List<Double> list = new ArrayList<>(4);
list.add(1.0);
list.add(2.0);
list.add(3.0);
list.add(4.0); //获取一个顺序流
Stream<Double> stream = list.stream();
System.out.println(stream.isParallel());
//顺序流上转换成一个并行流
Stream<Double> parallelStream = stream.parallel();
Stream<Double> unordered = parallelStream.unordered();//将流里面的元素设置无序
System.out.println(parallelStream.isParallel());
//并行流上转换成一个顺序流
Stream<Double> sequential = parallelStream.sequential();
System.out.println(sequential.isParallel());
}
- 处理并行流
获得并行流后,如果环境支持并行处理,那么在该流上发生的操作就可以并行执行。区别于顺序流,并行流的相关操作发生在不同的线程上。一般来说,应用到并行流上的任何操作都必须是无状态的,不干预的,并且具有关联性的。这样子可以确保在并行流上执行操作得到的结果,和在顺序流上执行相同操作得到的结果相同。
上一篇博客中,我们整理到了缩减操作,reduce()方法的第3个方法,就是专门用来指定如何合并并行结果的。
reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)在这个版本中,第三个函数将第二个函数得到的2个值合并起来。
以下代码使用并行流,计算一个集合中元素的积:
public static void main(String[] args) throws Exception
{
List<Integer> list = new ArrayList<>(4);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//直接从集合中获取并行流,然后执行缩减操作,下面的代码输出24
System.out.println(list.parallelStream().reduce(1, (a, b) -> a * b, (a, b) -> a * b));
}
处理并行流,有2点要注意:
1,在对并行流做缩减操作时,reduce()函数的第2个参数和第3个参数可以是做相同的操作,也可以是不同的操作,在有些情况下,这2个参数做的操作必须是不同的。来看下面这个例子:
public static void main(String[] args) throws Exception
{
List<Double> list = new ArrayList<>(4);
list.add(1.0);
list.add(2.0);
list.add(3.0);
list.add(4.0);
//直接从集合中获取并行流,然后执行缩减操作,下面的代码输出24
//下面的代码输出4.898979485566357,这里是顺序流
System.out.println(list.stream().reduce(1.0, (a, b) -> a * Math.sqrt(b)));
//下面的代码输出1.8612097182041991,这里是并行流,正确
System.out.println(list.parallelStream().reduce(1.0, (a, b) -> a * Math.sqrt(b), (a, b) -> a * b));
//下面的代码输出1.8612097182041991,这里是并行流,错误
System.out.println(list.parallelStream().reduce(1.0, (a, b) -> a * Math.sqrt(b), (a, b) -> a * Math.sqrt(b))); }
上面的代码中,累加器函数将2个元素的平方根相乘,但是合并器则将部分结果相乘,所以这2个函数是不同的,如果累加器函数和合并器函数是同一个函数,这将导致错误,因为当合并2个部分结果的时,相乘的是它们的平方根,而不是部分结果自身。值得注意的是,上面对reduce()方法的调用中,如果将流改成顺序流,操作将肯定得到正确的结果,所以我们在测试的时候也可以取值顺序流操作的结果来作为检验标准。
2,在使用并行操作时,关于流还有一点需要注意就是元素的位置。流可以时候有序的,也可以是无序的。一般来说,如果数据源是有序的,那么流也就是有序的。但是,在使用并行流的时候,有时候允许流是无序的这样子可以死获得性能上的提升。当并行流无序时,流的每个部分都可以被单独操作,而不是与其他部分协调。当操作的顺序不重要时,可以调用unordered()方法来指定无序行为。
其实有些api本身就是有序的或者说无序的,比如forEach()方法不一定保留并行流的顺序,但是在对并行流的每个元素执行操作时希望保留顺序的话,可以使用forEachOrdered()方法。
流API--使用并行流的更多相关文章
- Fork/Join框架与Java8 Stream API 之并行流的速度比较
Fork/Join 框架有特定的ExecutorService和线程池构成.ExecutorService可以运行任务,并且这个任务会被分解成较小的任务,它们从线程池中被fork(被不同的线程执行)出 ...
- JAVA8给我带了什么——并行流和接口新功能
流,确定是笔者内心很向往的天堂,有他之后JAVA在处理数据就变更加的灵动.加上lambda表达不喜欢都不行.JAVA8也为流在提供另一个功能——并行流.即是有并行流,那么是不是也有顺序流.没有错.我前 ...
- Java8新特性 并行流与串行流 Fork Join
并行流就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流. Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作. Stream API 可以声明性地通过 para ...
- java8新特性——并行流与顺序流
在我们开发过程中,我们都知道想要提高程序效率,我们可以启用多线程去并行处理,而java8中对数据处理也提供了它得并行方法,今天就来简单学习一下java8中得并行流与顺序流. 并行流就是把一个内容分成多 ...
- 三、并行流与串行流 Fork/Join框架
一.并行流概念: 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性的通过pa ...
- Java8新特性 - 并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性地通过parallel()和 ...
- java8学习之收集器枚举特性深度解析与并行流原理
首先先来找出上一次[http://www.cnblogs.com/webor2006/p/8353314.html]在最后举的那个并行流报错的问题,如下: 在来查找出上面异常的原因之前,当然得要一点点 ...
- 【Java8新特性】关于并行流与串行流,你必须掌握这些!!
写在前面 提到Java8,我们不得不说的就是Lambda表达式和Stream API.而在Java8中,对于并行流和串行流同样做了大量的优化.对于并行流和串行流的知识,也是在面试过程中,经常被问到的知 ...
- Stream并行流详解
1.并行与并发的区别 在说到并行的时候,相信很多人都会想到并发的概念.那么并行和并发两者一字之差,有什么区别呢? 并行:多个任务在同一时间点发生,并由不同的cpu进行处理,不互相抢占资源 并行: 并发 ...
随机推荐
- 【三分法】hdu2438 Turn the corner
Problem Description Mr. West bought a new car! So he is travelling around the city.One day he comes ...
- 前端学习:html基础学习四
7.HTML表格(主要内容<table><caption><tr><th><td>标记) <table>标记 基本格式 < ...
- python写unix口令破解器
看了python绝技做出来的unix口令破解器 首先需要crypt. python并不自带!! windows下pip安装失败= = 后来直接去kali敲了 附件:jiami.txt #假设是unix ...
- deeplearning.ai 人工智能行业大师访谈 Yoshua Bengio 听课笔记
1. 如何走上人工智能的研究的?Bengio说他小时候读了很多科幻小说,1985年(64年出生,21岁)研究生阶段开始阅读神经网络方面的论文,对这个领域产生了热情. 2. 如何看深度学习这些年的发展? ...
- COGS 2482. Franky的胡子【二分,高精度】
2482. Franky的胡子 ☆ 输入文件:beard.in 输出文件:beard.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述] Franky很苦恼他一直 ...
- SSL数字证书Nginx配置部署
由于小程序和Ios端的需要,公司的项目需要从原来的http协议扩展到https协议,因为项目本来就有采用nginx做了负载均衡,但是之前配置nginx的时候并没有配置关于https的内容,所以需要做这 ...
- 阻止浏览器冒泡事件,兼容firefox和ie
//得到事件 function getEvent(){ if(window.event) {return window.event;} func=getEvent.caller; while(func ...
- 你必须知道的session与cookie
Session本质 提到Session我们能联想到的就是用户登录功能,而本身我们使用Session的基础是通过url进行访问的,也就是使用http协议进行访问的,而http协议本身是无状态的,那么问题 ...
- 应用fstream格式化输出
我举一个我应用的例子 file.open("shoroud.jrf" ,ios_base::trunc); //打开文件,清空文件内容 if(!file.good()) { pri ...
- [国嵌笔记][028][Bootloader设计蓝图]
Bootloader的作用就是启动Linux内核 U-Boot简介 1.U-Boot是用于多种嵌入式CPU(ARM.x86.MIPS等)的bootloader程序,U-Boot不仅支持嵌入式Linux ...