parallelStream()并行滥用的后果

Java~ForkJoinPool + parallelStream实现并行快速处理数据流 文章目录ForkJoinPoolinvoke、execute和submit区别parallelStream实现快速处理数据流 ForkJoinPool 说起ForkJoinPool先说Fork/Join框架 我们通过Fork和Join这两个单词来理解一下Fork/Join框架。Fork就是把一个大任务切分 为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结 果。比如计算1+2+…+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和, 最终汇总这10个子 阅读详情
AI摘要

本文深入探讨Java中parallelStream()的使用误区与正确实践,包括线程安全、公共线程池问题、ThreadLocal失效及适用场景。强调并行流在CPU密集型任务的优势,指出在IO密集型场景下的限制。

背景

 对于java开发从业人员来说,并发编程是绕不开的话题,juc并发包下提供了一系列多线程场景解决方案。
 随着jdk1.8的普及,多线程处理问题,除了使用使用线程池(ExecutorService),很多人选择了parallelStream() 并行流,底层使用forkjoin实现并行处理。
 那么并行和并发又有什么区别?究竟改如何选择?滥用时又会有什么影响?
  这些问题我分以下几篇文章进行详细说明:
  1. 多线程并发和并行的区别
  2. parallelStream()并行滥用的后果 (本文)
  3. forkjoin和forkjoinpool讲解
  4. 线程池正确用法

坑点挨个举例

线程不安全

 随着java8 stream的普及,很多人开始使用并行流parallelStream(),进行并行计算,很多人会忽略一个问题:
 parallelStream()加入这行代码,就成了多线程,HaashMap线程不安全,会导致各种多线程问题。

		// 线程不安全的错误例子
		HashMap<String, Object> hashMap = new HashMap<>();
        numList.parallelStream().forEach(curr -> {
            hashMap.put(curr);
        });
		// 应该使用ConcurrentHashMap
		ConcurrentHashMap<String, Object> concurrentHashMap = new ConcurrentHashMap<>();
        numList.parallelStream().forEach(curr -> {
            concurrentHashMap.put(curr);
        });

公共commonPool导致程序卡顿

 cpu和内存都正常的情况下,生产环境遇到一次,脚本卡住几个小时才执行完,线程堆栈分析发现在下面代码线程进入waiting状态,而且是偶发。
 parallelStream()底层用的ForkJoinPool.commonPool();进行并行计算。代码中多个脚本同时用到parallelStream时,会共用线程池,一个脚本io慢,其他脚本都等等,用到的脚本越多,卡的时间越长。
 这一点非常重要:大部分人使用parallelStream不知道底层原理,把parallelStream当做多线程使用,这个非常危险,用的地方越多,程序卡顿时间越长。

		// 脚本a
		aaaList.parallelStream().forEach(curr -> {
            // 大量数据库查询等脚本代码
        });

		// 脚本b
		bbbList.parallelStream().forEach(curr -> {
            // 大量数据库查询等脚本代码
        });

并行代码中Threadlocal失效

 java开发中,我们经常会用到Threadlocal。parallelStream()是一个隐式线程池,比如:读写分离的连接名称、request通用获取等等,并行代码块中都将失效。

parallelStream()正确用法

  • cpu密集型的运算
    parallelStream底层使用和cpu核数一样多的ForkJoinPool并行计算,适合cpu密集型业务直接使用。
		// 正常使用即可,并行为计算而生
		aaaList.parallelStream().forEach(curr -> {
            // 正常编写业务代码
        });
  • io密集的多线程场景
    首先io密集场景适合使用线程池,不建议使用parallelStream()
    如果非要使用,可以做如下优化:
    io密集的业务,消耗cpu较少,出现慢sql等场景会导致线程等待,不能使用默认ForkJoinPool.commonPool(),自定义ForkJoinPool。
		// 并行代码放到ForkJoinPool中执行,就不再使用公共ForkJoinPool.commonPool()
 		ForkJoinPool forkJoinPool = new ForkJoinPool();
        forkJoinPool.execute(() -> {
            aaaList.parallelStream().forEach(curr -> {
            // 正常编写业务代码
        });
        });

注意事项总结

  • 并行代码块中需要使用AtomicInteger、ConcurrentHashMap等线程安全类。
  • parallelStream默认使用的commonPool,在io密集场景下不可大量使用
  • 数量级小的计算就别用并行了,cpu切换耗时反而慢
  • 在用到threadlocal的情景下,谨慎使用parallelStream和线程池,多线程中无法获取主线程的threadlocal。
  • 如果完全不懂parallelStream底层原理,建议不要使用
Java并行流parallelStream()下InheritableThreadLocal引起的问题 在并行流中,由于线程池的调度机制,父线程有可能会参与到并行流线程池的调度。如果父线程的上下文在某个时刻被清理,那么后续拷贝到子线程的上下文可能为空,导致上下文丢失的问题。原因在于并行流的设计比较特殊,父线程也有可能参与到并行流线程池的调度,那如果 方法被父线程执行,那么父线程的上下文会被清理。导致后续拷贝到子线程的上下文都为 null,同样产生丢失上下文的问题。可能会出现不同的行为,导致上下文丢失的问题。时,不会出现父线程上下文被清理导致的上下文丢失问题。在并行流场景下可能会出现上下文丢失的问题,而使用。 阅读详情

相关推荐

EFR32无线SoC开发指南:从环境搭建到性能优化

物联网边缘设备开发中,无线SoC芯片的选择与开发环境配置是关键第一步。EFR32作为Silicon Labs推出的多协议无线SoC系列,配合Simplicity Studio IDE,为开发者提供了完整的解决方案。本文以EFR32xG22开发套件为例,详细介绍开发环境搭建、工程创建、硬件配置等核心环节,特别针对RAILtest示例工程进行深入解析。通过实际案例演示如何配置无线参数、优化低功耗模式,并分享串口终端交互、吞吐量测试等实战技巧。对于开发者常见的问题如设备识别失败、无线通信异常等,提供了系统化的排查

weixin_30342363的博客 352

parallelStream()使用及避坑

parallelStream()是Java 8 Stream API中的一种方法,它允许在多个线程上并行执行流操作。这使得我们能够更有效地利用现代多核处理器的能力。

freeStyle_liu的博客 5270

LeRobot 入门教程(三)在仿真环境和自定义机器人上部署 LeRobot

本教程详细介绍了基于真实世界机器人和仿真环境的模仿学习实现方法,涵盖数据采集、训练策略和评估全流程。在真实机器人部分,重点讲解了远程操作设置、摄像头配置、数据集记录与管理技巧、策略训练(支持GPU/MPS设备)以及模型评估。仿真环境部分则演示了gym-hil的安装使用、模拟数据采集和策略训练。此外,教程还提供了自定义机器人集成指南,包括电机选择、接口继承、传感器/动作特征定义、连接管理和校准配置等核心步骤。所有方法均支持HuggingFace数据集中心和Weights & Biases工具链,为机器

2506_90492529的博客 2400

Java8 并行流(parallelStream)原理分析及注意事项

众所周知,Java 使用Stream流做多线程处理是非常方便的。随着并行编程越来越流行,Java从1.7就开始提供了Fork/Join 支持并行处理,并且在1.8版本进一步加强了相关功能。并行处理就是将任务拆分子任务,分发给多个处理器同时处理之后进行合并。本文将会对并行流(parallelStream)原理分析及注意事项进行详细介绍。

Clearlove_S7的博客 3万+

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2659

危废焚烧优化控制系统设计与实现:基于数据驱动的控制参数预测

本文提出了一种基于数据驱动的危险废物焚烧过程优化控制方法。系统利用历史运行数据和实时监测数据,通过深度学习模型预测关键控制参数,实现焚烧过程的智能化控制。系统采用Python开发,结合TensorFlow/PyTorch框架,构建了完整的数据采集、预处理、特征工程、模型训练和实时预测闭环系统。该系统能够处理多变量非线性关系,适应工况变化,从历史数据中学习最优控制策略,相比传统PID控制方法具有显著优势。论文详细介绍了系统架构、算法设计和实现细节,为危废焚烧过程的优化控制提供了有效解决方案。

huanghm88的专栏 206

parallelStream()并行流操作

在Java-Stream流式编程中已经讲了流编程的使用方法,但是stream()是串行操作的,也可以说是线程安全的。但是parallelStream()恰恰相反,是并行操作的,是线程不安全的,两者的执行效率的话肯定是parallelStream()要快,毕竟是多线程的,但是这就就会涉及到线程安全的问题了,一旦涉及到线程安全的问题,那些线程不安全的集合类型我们是一个都不能用的了,像什么HashMap,ArrayList,都不能用了,只能用线程安全的集合了。如果还纠结为什么线程不安全不能用或者为什么线程不安全的

qq_45735918的博客 5050

嵌入式工程师成长之路(7)——算法学习

算法大全1、风仲达——算法笔记2、坐在马桶上学算法3、啊哈算法4、深度强化学习实验室。

云轩阁 4万+

Parallel Stream(并行流)

Parallel Stream(并行流) 以上介绍的创建Stream流对象的3种方法都是创建的串行流(Serial Stream),串行流就是将源数据转换为一个流对象,然后单线程下执行聚合操作的流(也就是单一管道流) 并行流(Parallel Stream)就是将数据分为多个子流对象进行多线程操作(也就是多个管道流) 如下图介绍: 简述:在创建Stream流对象时,默认创建都是串行流。两种方式创建Stream并行流:第1种方式是通过Collection集合接口中的parallelStream()方法直

m0_53821599的博客 8926

Spring AI Alibaba实战训练营-14基于A2A协议智能体应用开发指南

本文介绍了基于A2A协议的智能体应用开发流程,主要包括客户端和服务端两个模块的实现。关键技术包括A2A通信协议、Nacos服务发现、Spring AI Alibaba框架和DashScope通义千问API。开发步骤涵盖环境准备(JDK17、Maven、Nacos)、项目创建、依赖配置(重点引入spring-ai-alibaba相关组件)以及Nacos和DashScope的核心配置。整个系统架构采用客户端通过Nacos发现服务端Agent,再调用阿里云AI服务的模式,实现了AI能力的解耦与复用。

program哲学 505

Agent 智能体学习指南:从入门到求职的完整路线

AI Agent 不是更长的 prompt,而是一类系统设计——模型在受控环境里观察状态、选择动作、调用工具、接收反馈。本文系统梳理 Agent 的 5 个核心概念、7 个关键模块(Goal/State/Context/Tools/Loop/Guardrails/Eval)、三条学习路线(工程落地/研究算法/求职作品)、框架选型策略(LangGraph/OpenAI Agents SDK/Pydantic AI 等场景推荐),以及可执行的 7 天最小项目计划(从概念到简历 bullet)。

program哲学 229

Java 并行流(parallelStream)详解

本篇博客详细介绍了Java并行流以及其使用方式。

郎逸的博客 3055

25、BDS-3卫星信号性能与PPP-B2b增强消息完整性分析

本文对BDS-3卫星信号性能及PPP-B2b增强消息的完整性进行了系统分析。评估了MEO、IGSO和GEO卫星的轨道与时钟精度,得出BDS-3总体SISRE为0.25 m,系统完整性可覆盖99.999%的误差。分析表明SIS中断主要由时钟调整和轨道机动引起,个别卫星存在因境外监测受限导致的非计划中断。通过自研解码软件对PPP-B2b增强消息进行采集与解析,实验结果显示BDS-3和GPS的平均历元完整性率均高于98.55%,其中卫星掩码和时钟校正消息的完整性率超过99.8%。研究还发现IGSO卫星相比MEO卫

quiet的专栏 145

谈谈并行流parallelStream

一、parallelStream内部使用了哪些线程 Java8中提供了能够更方便处理集合数据的Stream类,其中parallelStream()方法能够充分利用多核CPU的优势,使用多线程加快对集合数据的处理速度。不熟悉Stream类的同学,可以先参考我的另外一篇文章Java8中Stream的常用方法 以一个简单的例子,来看看parallelStream内部到底使用了哪些线程 Integer[] array = new Integer[]{1, 2, 3, 4, 5};

阳阳的博客 3万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

小白趟坑---慎用 parallelStream().forEach()

小白趟坑—慎用 parallelStream().forEach() ps: 本系列第一贴,也可能是最后一贴。 循环遍历集合,是日常开发中常用的功能,自从java8引入lambda之后,除了常规的foreach之外,可以将遍历转为流操作,然后进行遍历,提升效率。 parallelStream() 和 stream(),都可以讲集合转化为流,通过字面意思,可以看出 parallelStream() 是并行的操作,在大数据量下会优于 stream(),于是就有了以下代码片段(片段经过简化,会有不符合编程规范的地

u011119942的博客 2万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

并行流parallelStream

java 8新特性,并行流parallelStream的用法与实现原理,parallelStream如何解决threadLocal传值问题

匿 <h7>应该不可以</h7> 1998

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java 多线程之并行流(parallelStream)

并行流是Java中Stream API的一部分,用于在多核处理器上并行执行流操作。在Java 8及更高版本中引入的Stream API提供了一种新的处理集合的方式,使得开发者能够更轻松地进行数据处理和操作。在使用Stream API时,可以将集合转换为流,然后进行各种操作,例如过滤、映射、排序等。在这个过程中,流可以是串行流(Sequential Stream)或并行流(Parallel Stream)。并行流通过使用多线程并行处理数据,充分利用多核处理器的优势,从而在某些情况下提高处理速度。

QIFU的专栏 1万+

探讨并行流(parallelStream)

Java8中提供了能够更方便处理集合数据的Stream类,其中parallelStream()方法能够充分利用多核CPU的优势,使用多线程加快对集合数据的处理速度。parallelStream主要用于利用处理器的多个核心。通常,任何Java代码都有一个处理流,在这里它是按顺序执行的。然而,通过使用并行流,我们可以将代码分成多个流,这些流在不同的内核上并行执行,最终的结果是各个结果的组合。然而,处理的顺序不在我们的控制之下。

u010272132的博客 2142

Java中parallelStream的使用

前言: 各位读者们好久不见,最近博主我一直在实习中, 而且也准备校招,刷了很多很多的题目,今天在实习中看到了师兄写的代码中使用到了parallelStream()这个并行流计算,所以我想写一篇博客总结一下这个parallelStream新特性的具体使用。 1、什么是parallelStream? 众所周知,stream流式计算是Java8中新添的一种新特性,可以把stream流理解为串行的流式计算,而parallelStream是一种多线程并行流式计算。 2、parallelStream的作用在哪?或者说有

小贱贱的博客 1万+

parallelStream并行流使用踩坑,集合安全

后续在调试过程中发现,resultList中的数据量会随机少一两个数据,比如codeList中数据为1,2,3,4,5. 经过过滤后本应添加到resultList中的数据为1,2,3,4. 但是发现只加进来了1,2,3或者是1,2,4 会有数据确实的情况,本来以为是过滤条件的问题,排查后发现过滤条件没有问题,开始怀疑是并行流的问题。在添加数据时,他会先复制原来的数组然后在新的数组上面进行添加,最后再将新数组覆盖到旧的上面。如果在操作过程中切换了线程到读,此时的旧数组并未被覆盖,读取到的还是原来的数组。

m0_52796363的博客 3353

并行流ParallelStream中隐藏的陷阱

点击上方蓝字 ↑↑ Throwable文摘关注公众号设置星标,不定时推送高质量原创文章关注前提这篇文章介绍一下日常开发中并行流ParallelStream中隐藏的陷阱,这个问题其实离我们...

Throwable 4269

parallelstream启动的线程数_谈谈并行流parallelStream

一、parallelStream是什么Java8中提供了能够更方便处理集合数据的Stream类,其中parallelStream()方法能够充分利用多核CPU的优势,使用多线程加快对集合数据的处理速度。不熟悉Stream类的同学,可以先参考我的另外一篇文章Java8中Stream的常用方法parallelStream()方法的源码如下: /** * @return a possibl...

weixin_39653311的博客 3439

滥用java8 parallelStream

滥用Java8新特性parallelStream()

技术杠精的博客 935
上一篇: 多线程并发和并行的区别
下一篇: forkjoin和forkjoinpool讲解
鲫鱼哥
博客等级 码龄10年 18粉丝 36原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值