流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进行处理,不互相抢占资源 并行: 并发 ...
随机推荐
- Markdown 常用语法
1.标题 # 一级标题 ## 二级标题 ### 三级标题 2.字体 *斜体* **粗体** ~~删除线~~<u>下划线</u> 3.引用 > 引用文字 4.无序列表 - ...
- 【最大权闭合子图】bzoj4873 [Shoi2017]寿司餐厅
4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 369 Solved: 256[Submit][Status ...
- 【高精度乘法】NOIP2003麦森数
题目描述 形如2^{P}-12P−1的素数称为麦森数,这时PP一定也是个素数.但反过来不一定,即如果PP是个素数,2^{P}-12P−1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的 ...
- (GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序
一.综述 如何采集图片?在windows环境下,我们可以使用dshow,在linux下,也有ffmpeg等基础类库,再不济,opencv自带的videocapture也是提供了基础的支撑.那么 ...
- Android基础_ContentProvider组件
一.了解Contentprovider组件 1.1Contentprovider是数据的提供者,Android四大组件之一,程序之间数据共享的接口 1.2activity系统中对数据的访问限制十分严格 ...
- MyEclipse10.7 10.6导出war文件报错 “SECURITY ALERT: INTEGERITY CHECK ERROR”
myeclipse10.7的版本破解后,导出war包时报“SECURITY ALERT: INTEGERITY CHECK ERROR”的错误. 经过测试本次破解可以解决此错误,只需替换一个jar文件 ...
- 【一小时入门】webpack 入门指南
什么是 webpack? webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都作为模块来使用和处理. 我们可以 ...
- [bzoj2574] [Poi1999]Store-Keeper
坑啊.. 膜了半天byvoid大爷的题解.https://www.byvoid.com/blog/poi-1999-mag/?replytocom=1335/ 一开始从人的位置bfs一波,看看能走到初 ...
- BZOJ2425: [HAOI2010]计数
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2425 其实能够构成的数就是原数的排列(算前导0),然后组合计数一下就可以了. #include ...
- Django App(四) Submit a form
经过前面的努力,到这里我们已经基本完成了,从服务器到浏览器的数据下发,还没有解决从浏览器到服务器的数据上传,这一节将创建一个Form获取从浏览器提交的数据 1.新建Form 接着前面建的项目,网上调查 ...