Stream居然还有这种新玩法?完全可以解放双手了!

本文介绍了Java8的ParallelStream,揭示了并行流背后的ForkJoinPool工作原理,讨论了并行流可能遇到的线程安全问题,并通过实例分析了在高并发情况下并行流的执行情况,提醒开发者在使用并行流时需注意的事项和考虑的场景。
摘要由CSDN通过智能技术生成

一、 前言

在说 parallelStream 之前, 一定要了解 Stream 以及它的基本操作

二、什么是 ParallelStream

上文讲到的 Java8 Stream 流在执行时候是串行化的, 如果说任务执行的耗时比较长, 可以使用 Stream 的 “兄弟流” ParallelStream

防止误导, 并非耗时就一定要使用并行, 根据不同的业务场景, 合理的使用即可

parallelStream 是一种并行流, 意思为处理任务时并行处理, 这里和并发编程就有了千丝万缕的关系

前提是硬件支持, 如果单核 CPU, 只会存在并发处理, 而不会并行

这篇文章主要是说明 ParallelStream 其中一个可能为成为埋雷的点

项目中业务使用的并行流真的会都并行处理么?

三、如何使用 ParallelStream

ParallelStream 在使用上与 Stream 无区别, 本质返回的都是一个流, 只不过底层处理时 根据条件判断是并行或者是串行

[图片上传失败…(image-b06783-1604490624520)]

并行流并不会按照原本的顺序轨迹执行, 而是 随机执行, 当然对于这种 forEach 输出也可以做到顺序串行, 但这个不在文章中的重点

四、ForkJoinPool

相信如果在项目中实际使用过并行流的小伙伴, 一定会知道 ForkJoinPool

没错, 并行流底层就是使用的 ForkJoinPool, 一种 工作窃取算法线程池

ForkJoinPool 的优势在于, 可以充分利用多 CPU 的优势,把一个任务拆分成多个"小任务", 把多个"小任务"放到多个处理器核心上并行执行; 当多个"小任务"执行完成之后, 再将这些执行结果合并起来

五、并行流的陷阱

5.1 线程安全问题

只要是并行处理, 如果在流程中的操作产生了竞态条件, 就会存在线程安全问题

这里举个例子进行说明具体问题

public static void main(String[] args) {
    List<Integer> integerList = Lists.newArrayList();
    List<String> strList = Lists.newArrayList();

    int practicalSize = 1000000;

    for (int i = 0; i < practicalSize; i++) {
        strList.add(String.valueOf(i));
    }

    strList.parallelStream().forEach(each -> {
        integerList.add(Integer.parseInt(each));
    });

    log.info("  >>> integerList 预计长度 :: {}", practicalSize);
    log.info("  >>> integerList 实际长度 :: {}", integerList.size());
}
/**
 * >>> integerList 预估长度 :: 1000000
 * >>> integerList 实际长度 :: 211195
 */

上面这段程序运行流程说明如下:

1、创建了两个 List, 分别是 String、Integer 类型

2、向 strList 插入 1000000 条记录

3、使用并行流将 strList 中的数据格式化为 Integer 并添加到 integerList

4、输出 integerList

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值