hello !我是小小,今天是本周的第二篇,本篇将会着重的讲解关于Java并行流的知识

前言

在之前如果需要处理集合需要先手动分成几部分,然后为每部分创建线程,最后在合适的时候合并,这是手动处理并行集合的方法,在java8中,有了新功能,可以一下开启并行模式。

并行流

认识开启并行流

并行流是什么?是把一个流内容分成多个数据块,并用不同线程分别处理每个不同数据块的流。例如,有下面一个例子,在List中,需要对List数据进行分别计算,其代码如下所示:

List<Apple> appleList = new ArrayList<>(); // 假装数据是从库里查出来的for (Apple apple : appleList) {apple.setPrice(5.0 * apple.getWeight() / 1000);
}

在这里,时间复杂度为O(list.size),随着list的增加,耗时也在增加。并行流可以解决这个问题,代码如下所示:

appleList.parallelStream().forEach(apple -> apple.setPrice(5.0 * apple.getWeight() / 1000));

这里通过调parallelStream()说明当前流为并行流,然后进行并行执行。并行流内部使用了默认的ForkJoinPool线程池,默认线程数为处理器的核心数。

测试并行流

普通代码如下所示:

public static void main(String[] args) throws InterruptedException {List<Apple> appleList = initAppleList();Date begin = new Date();for (Apple apple : appleList) {apple.setPrice(5.0 * apple.getWeight() / 1000);Thread.sleep(1000);}Date end = new Date();log.info("苹果数量:{}个, 耗时:{}s", appleList.size(), (end.getTime() - begin.getTime()) /1000);
}

输出的内容为耗时4s。

并行代码如下所示:

List<Apple> appleList = initAppleList();Date begin = new Date();
appleList.parallelStream().forEach(apple ->{apple.setPrice(5.0 * apple.getWeight() / 1000);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});
Date end = new Date();
log.info("苹果数量:{}个, 耗时:{}s", appleList.size(), (end.getTime() - begin.getTime()) /1000);

输出结果为耗时1s。可以看到耗时大大提升了3s。

并行流拆分会影响流的速度

对于并行流来说需要注意以下几点:

  1. 对于 iterate 方法来处理的前 n 个数字来说,不管并行与否,它总是慢于循环的,

  2. 而对于 LongStream.rangeClosed() 方法来说,就不存在 iterate 的第两个痛点了。它生成的是基本类型的值,不用拆装箱操作,另外它可以直接将要生成的数字 1 - n 拆分成 1 - n/4, 1n/4 - 2n/4, ... 3n/4 - n 这样四部分。因此并行状态下的 rangeClosed() 是快于 for 循环外部迭代的

代码如下所示:

package lambdasinaction.chap7;import java.util.stream.*;public class ParallelStreams {public static long iterativeSum(long n) {long result = 0;for (long i = 0; i <= n; i++) {result += i;}return result;}public static long sequentialSum(long n) {return Stream.iterate(1L, i -> i + 1).limit(n).reduce(Long::sum).get();}public static long parallelSum(long n) {return Stream.iterate(1L, i -> i + 1).limit(n).parallel().reduce(Long::sum).get();}public static long rangedSum(long n) {return LongStream.rangeClosed(1, n).reduce(Long::sum).getAsLong();}public static long parallelRangedSum(long n) {return LongStream.rangeClosed(1, n).parallel().reduce(Long::sum).getAsLong();}}
package lambdasinaction.chap7;import java.util.concurrent.*;
import java.util.function.*;public class ParallelStreamsHarness {public static final ForkJoinPool FORK_JOIN_POOL = new ForkJoinPool();public static void main(String[] args) {System.out.println("Iterative Sum done in: " + measurePerf(ParallelStreams::iterativeSum, 10_000_000L) + " msecs");System.out.println("Sequential Sum done in: " + measurePerf(ParallelStreams::sequentialSum, 10_000_000L) + " msecs");System.out.println("Parallel forkJoinSum done in: " + measurePerf(ParallelStreams::parallelSum, 10_000_000L) + " msecs" );System.out.println("Range forkJoinSum done in: " + measurePerf(ParallelStreams::rangedSum, 10_000_000L) + " msecs");System.out.println("Parallel range forkJoinSum done in: " + measurePerf(ParallelStreams::parallelRangedSum, 10_000_000L) + " msecs" );}public static <T, R> long measurePerf(Function<T, R> f, T input) {long fastest = Long.MAX_VALUE;for (int i = 0; i < 10; i++) {long start = System.nanoTime();R result = f.apply(input);long duration = (System.nanoTime() - start) / 1_000_000;System.out.println("Result: " + result);if (duration < fastest) fastest = duration;}return fastest;}
}

共享变量会造成数据出现问题

public static long sideEffectSum(long n) {Accumulator accumulator = new Accumulator();LongStream.rangeClosed(1, n).forEach(accumulator::add);return accumulator.total;
}public static long sideEffectParallelSum(long n) {Accumulator accumulator = new Accumulator();LongStream.rangeClosed(1, n).parallel().forEach(accumulator::add);return accumulator.total;
}public static class Accumulator {private long total = 0;public void add(long value) {total += value;}
}

并行流的注意

  1. 尽量使用 LongStream / IntStream / DoubleStream 等原始数据流代替 Stream 来处理数字,以避免频繁拆装箱带来的额外开销

  2. 要考虑流的操作流水线的总计算成本,假设 N 是要操作的任务总数,Q 是每次操作的时间。N * Q 就是操作的总时间,Q 值越大就意味着使用并行流带来收益的可能性越大

  3. 对于较少的数据量,不建议使用并行流

  4. 容易拆分成块的流数据,建议使用并行流

关于作者

我是小小,一枚一线程序猿,我们下期再见~bye

END

「 往期文章 」

文末送书 | DB-Engines 12月数据库排名:PostgreSQL有望获得「2020年度数据库」荣誉?

文末送书 | C++ 20发布后,这个老牌编程语言又“真香”了

忠告 | 小小对Java30岁程序猿的忠告,强烈推荐!

扫描二维码

获取更多精彩

小明菜市场

来源:网络(侵删)

图片来源:网络(侵删)

程序| 只要使用这个功能,程序运行速度瞬间提升,高到离谱!相关推荐

  1. 编写一个Java应用程序,实现下列功能: ●程序随机分配给客户一个1~100之间的整数。

    编写一个Java应用程序,实现下列功能: ●程序随机分配给客户一个1~100之间的整数. ●用户在输入对话框中输入自己的猜测. ●程序返回提示信息,提示信息分别是:"猜大了".&q ...

  2. 怎么在短时间内提高计算机水平,五个有效方法让电脑运行速度瞬间提升数倍

    很多人不知道自己电脑需要更换什么配件能够让其运行速度提升,往往花很多钱买来配件,电脑的运行速度并没有明显改善,在这里讲的是如何花最少的钱让自己电脑的运行速度提升数倍,当然对于并不缺钱的人可以直接更换电 ...

  3. 现阶段的微信小程序能实现直播功能么?

    对于没有技术背景的商家要使用微信小程序的直播,可以直接用来客推的免费开源版本,代码直接开源还接入微信小程序直播!符合开通条件的商家都可以快速制作直播小程序商城,享受小程序直播带来的早期红利 微信小程序 ...

  4. 条令考试小程序辅助器_在线考试题库小程序开发有哪些功能?

    因疫情的关系导致很多考试都没办法在线下进行,所以在线考试和考试题库小程序就运营而生了.那么考试题库小程序可以开发哪些功能呢? 1.同步练习:为了强化学生课堂所学内容,小程序会为用户提供相应的同步练习课 ...

  5. c语言程序中的基本功能,c语言程序中的基本功能模块为什么?

    c语言程序中的基本功能模块为"函数".一个C语言程序可以由一个主函数和若干个函数构成:一个大的应用程序一般应该分为多个程序模块,每一个模块用来实现一个功能,而模块的功能是由函数完成 ...

  6. 为应用程序增加文件压缩功能

    [简介] --压缩文件可以认为是一个包装文件的容器.通过文件压缩,大量文件可以被打包起来并当作一个文件来看待.此外,压缩文件在尺寸上普遍比原文件小,如文本文件在压缩以后的平均大小是原来的40%.因此, ...

  7. 游戏开发需要具备哪些技术_生鲜小程序需要具备哪些功能板块?生鲜小程序开发...

    线上生鲜小程序开发让用户购买蔬菜水果更加便捷,不仅可以有利于发展生鲜行业之后的规模,而且也能够吸引更多的用户,低成本获客.那么,这样一款生鲜小程序需要具备哪些功能板块呢? 线上生鲜小程序需要具备什么? ...

  8. 小程序云开发搜索功能的实现正则_几行代码实现小程序云开发提现功能

    先看效果: 纯云开发实现,下面说使用步骤:一:开通商户的企业付款到领取功能说明地址: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php? ...

  9. java代码实现购物车小程序_使用Taro实现小程序商城的购物车功能模块的实例代码...

    Taro 是一套遵循 React 语法规范的 多端开发 解决方案. 现如今市面上端的形态多种多样,Web.React-Native.微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的 ...

最新文章

  1. 如何访问webService接口
  2. yum安装mysql步骤及报错ERROR 1045 (28000)
  3. 01:初识Redis
  4. (转载)Xcode中other linker flags的作用
  5. unicode环境下用CFile读取txt的若干疑惑,该如何处理
  6. php filter 文件包含,php://filter(文件包含漏洞利用)及php://input
  7. JZOJ 4058. 【JSOI2015】子集选取
  8. android上传项目到码云_直播开源项目
  9. php 遍历文件夹并压成zip_php ZipArchive实现多文件打包下载实例
  10. [ZPG TEST 115] 字符串【归类思想】
  11. JDY-24M主机使用手册
  12. lpt监控安装_LPT说明书
  13. markdown语法进阶——字体、字号与颜色设置
  14. [英文邮件写作技巧] 表达感谢,提出问题,描述附件
  15. mmo游戏服务器性能指标,关于performance:厚积薄发MMORPG手游合理的性能参数
  16. html渐变不兼容,CSS实现兼容性的渐变背景(gradient)效果兼容众多浏览器
  17. python判断字符串是字母 数字 大小写
  18. 数据库巡检 java_美团MySQL数据库巡检系统的设计与应用
  19. 《C#高级编程》读书笔记
  20. Springboot大学生健康报送系统的设计与实现毕业设计源码091005

热门文章

  1. debian8.7.1安装zabbix3.2
  2. Flex中创建Accordion报错
  3. 【转载】消息队列RabbitMQ入门介绍
  4. sqlplus补丁包rlwrap-0.37的安装步骤(解决SQL的删除、上翻历史命令等)
  5. ASP.NET MVC基础入门.
  6. magento effects.js jquery.lazyload.js 冲突
  7. Linux中的终端、控制台、tty、pty等概念
  8. 【读书笔记】原型模式代码(C++) 第一版
  9. Linux学习笔记 文件服务Vsftp详细介绍
  10. java对mysql的简单操作的综合运用——修改密码系统