Java并行流parallelStream()下InheritableThreadLocal引起的问题
Java并行流parallelStream()下InheritableThreadLocal引起的问题
引起问题的代码。
List orgs00 = Arrays.asList(new Org("aaa"),new Org("bbb"),new Org("aa0"));List orgs = orgs00.parallelStream() .map(org -> {// 模拟从数据库中获取 Org 对象的操作// 这里可以是实际的数据库查询操作ConditionImpl cmd = new ConditionImpl();cmd.op("orgName", Op.eq, org.getOrgName());
// cmd.orderBy("name", OrderType.ASC);System.out.println("-----------------111111111111111111111111-");List select1 = getSuidRich().select(new Org(), cmd); //语句1:这句会调用数据库return new Org(org.getOrgName());}).collect(Collectors.toList());问题:语句1调用的方法有条词句:private static ThreadLocal>> sqlPreValueLocal;经过orgs00.parallelStream().map()) 执行调用语句1,sqlPreValueLocal是同一个本地变量吗?
并行流场景下使用 ThreadLocal, sqlPreValueLocal = new InheritableThreadLocal<>(); //语句1
或者
sqlPreValueLocal = new ThreadLocal<>();//语句2
用语句1有时上下文丢失,但用语句2不会, 可以解释为什么吗?
在并行流场景下,使用InheritableThreadLocal
和ThreadLocal
可能会出现不同的行为,导致上下文丢失的问题。下面我会解释一下为什么语句1有时会出现上下文丢失,而语句2不会。
- 使用
InheritableThreadLocal
(语句1):
InheritableThreadLocal
会使子线程继承父线程中的ThreadLocal
变量的值。在并行流中,由于线程池的调度机制,父线程有可能会参与到并行流线程池的调度。如果父线程的上下文在某个时刻被清理,那么后续拷贝到子线程的上下文可能为空,导致上下文丢失的问题。这种情况可能会导致语句1有时会出现上下文丢失的情况。
- 使用
ThreadLocal
(语句2):
ThreadLocal
不具备继承性,子线程不会继承父线程中的ThreadLocal
变量的值。因此,在并行流中使用ThreadLocal
时,不会出现父线程上下文被清理导致的上下文丢失问题。每个线程都有自己独立的ThreadLocal
副本,不会受到父线程的影响。
综上所述,使用InheritableThreadLocal
在并行流场景下可能会出现上下文丢失的问题,而使用ThreadLocal
则不会受到这种影响。因此,如果在并行流中需要使用ThreadLocal
来传递上下文,可以考虑使用ThreadLocal
而不是InheritableThreadLocal
,以避免上下文丢失的情况。
原因在于并行流的设计比较特殊,父线程也有可能参与到并行流线程池的调度,那如果 方法被父线程执行,那么父线程的上下文会被清理。导致后续拷贝到子线程的上下文都为 null,同样产生丢失上下文的问题。
以上结论不保证十分准确。
但有下面的测试实验结论:
// 1. parallelStream().map + sqlPreValueLocal = new InheritableThreadLocal<>();
// 很容易出现: No value specified for parameter 1
// 2. parallelStream().map + sqlPreValueLocal = new ThreadLocal<>();
// 不会出现: No value specified for parameter 1
// 2.5 stream().map + sqlPreValueLocal = new ThreadLocal<>();
// 不会出现: No value specified for parameter 1
// 1.5 stream().map + sqlPreValueLocal = new InheritableThreadLocal<>();
// 不会出现: No value specified for parameter 1
// 结论:只有1. parallelStream().map + InheritableThreadLocal 才会现现 No value specified for parameter 1
测试代码:
import java.util.List;
import java.util.stream.Collectors;import org.teasoft.bee.osql.Op;
import org.teasoft.bee.osql.api.SuidRich;
import org.teasoft.honey.osql.core.ConditionImpl;
import org.teasoft.honey.osql.shortcut.BF;//parallelStream().map并行流测ORM
public class StreamSelectTest3 {public static void main(String[] args) {List<Org> orgs00 = getSuidRich().select(new Org()); //约50条记录// 1. parallelStream().map + sqlPreValueLocal = new InheritableThreadLocal<>();
// 很容易出现: No value specified for parameter 1// 2. parallelStream().map + sqlPreValueLocal = new ThreadLocal<>();
// 不会出现: No value specified for parameter 1// 2.5 stream().map + sqlPreValueLocal = new ThreadLocal<>();
// 不会出现: No value specified for parameter 1// 1.5 stream().map + sqlPreValueLocal = new InheritableThreadLocal<>();
// 不会出现: No value specified for parameter 1// 结论:只有1. parallelStream().map + InheritableThreadLocal 才会现现 No value specified for parameter 1// 直接在map中进行数据库查询
// List<Org> orgs = orgs00.stream()List<Org> orgs = orgs00.parallelStream() // 这个才会.map(org -> {// 从数据库中获取 Org 对象的操作// 这里可以是实际的数据库查询操作ConditionImpl cmd = new ConditionImpl();cmd.op("orgName", Op.eq, org.getOrgName());System.out.println("-----------------111111111111111111111111-");List<Org> select1 = getSuidRich().select(new Org(), cmd);return new Org(org.getOrgName());}).collect(Collectors.toList());orgs.forEach(org -> System.out.println("Org name: " + org.getOrgName()));}static SuidRich getSuidRich() {return BF.getSuidRich();}
}
多线程测试测没有发现相应问题。
import java.util.List;import org.teasoft.bee.osql.api.SuidRich;
import org.teasoft.honey.osql.shortcut.BF;public class ThreadSelectTest2 extends Thread{// static SuidRich suidRich=BF.getSuidRich();public static void main(String[] args) throws Exception{ThreadSelectTest2 test[]=new ThreadSelectTest2[5];for (int i = 0; i < test.length; i++) {test[i]=new ThreadSelectTest2();test[i].start();}System.out.println("finished!");}// sqlPreValueLocal = new InheritableThreadLocal<>(); //没问题 , 没那么容易连不上
// sqlPreValueLocal = new ThreadLocal<>(); // 很容易连不上; 但没碰到 No value specified for parameter 1
// org.teasoft.bee.osql.BeeSQLException: The driver was unable to create a connection due to an inability to establish the client portion of a socket.
// This is usually caused by a limit on the number of sockets imposed by the operating system. This limit is usually configurable.
// For Unix-based platforms, see the manual page for the 'ulimit' command. Kernel or system reconfiguration may also be required.public void run() {SuidRich suidRich=BF.getSuidRich();List<Org> listOrg=suidRich.select(new Org()); //约50条for (int i = 0; i < 2; i++) {for (int j = 0; j < listOrg.size(); j++) {Org org = new Org(listOrg.get(i).getOrgName()); //拿外层每一条的值 又去查一遍;只是测试性能,不考虑业务正确与否suidRich.select(org);}}}}
相关文章:
Java并行流parallelStream()下InheritableThreadLocal引起的问题
Java并行流parallelStream()下InheritableThreadLocal引起的问题 引起问题的代码。 List orgs00 Arrays.asList(new Org("aaa"),new Org("bbb"),new Org("aa0"));List orgs orgs00.parallelStream() .map(org -> {// 模拟从数据库中获取 …...

【C++期末编程题题库】代码+详解18道
适合期末复习c看,或者刚入门c的小白看,有的题会补充知识点,期末复习题的代码一般比较简单,所以语法上没那么严谨。本文所有题目要求全在代码块的最上面。 目录 1、设计复数类 2、设计Computer类 3、实现相加的函数模板 4、圆类…...

一种DevOpts的实现方式:基于gitlab的CICD(一)
写在之前 笔者最近准备开始入坑CNCF毕业的开源项目,看到其中有一组开源项目的分类就是DevOpts。这个领域内比较出名的项目是Argocd,Argo CD 是一个用于 Kubernetes 的持续交付 (Continuous Delivery) 工具,它以声明式的方式实现了应用程序的…...
nodejs和vuejs的区别
一、vue项目开发中,两个经常混合使用。 不同: 1、概念不同: 一个是前端框架,一个是服务端语言。 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使…...

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和
目录 一、概述 二、节点名称 - nodeName 二、节点选择器 - nodeSelector 三、节点亲和性和反亲和性 3.1、亲和性和反亲和性 3.2、节点硬亲和性 3.3、节点软亲和性 3.4、节点反亲和性 3.5、注意点 四、Pod亲和性和反亲和性 4.1、亲和性和反亲和性 4.2、Pod亲和性/反…...

面试算法96:字符串交织
题目 输入3个字符串s1、s2和s3,请判断字符串s3能不能由字符串s1和s2交织而成,即字符串s3的所有字符都是字符串s1或s2中的字符,字符串s1和s2中的字符都将出现在字符串s3中且相对位置不变。例如,字符串"aadbbcbcac"可以由…...
什么是Vue.js的响应式系统(reactivity system)?如何实现数据的双向绑定?
Vue.js的响应式系统是指一种能够跟踪数据变化并实时更新相关界面的机制。它是Vue.js框架的核心特性之一。 在Vue.js中,你可以使用数据绑定语法将数据绑定到DOM元素上。当绑定的数据发生变化时,Vue.js会自动监听这些变化并更新相关的DOM元素。 Vue.js实…...
力扣labuladong一刷day52天LRU算法
力扣labuladong一刷day52天LRU算法 文章目录 力扣labuladong一刷day52天LRU算法概念一、146. LRU 缓存思路一:使用双向链表加map来手动实现。思路二:使用LinkedHashMap 概念 LRU的全称为Least Recently Used,翻译出来就是最近最少使用的意思…...

CCNP课程实验-06-EIGRP-Trouble-Shooting
目录 实验条件网络拓朴 环境配置开始排错错误1:没有配置IP地址,IP地址宣告有误错误2:R3配置了与R1不同的K值报错了。错误3:R4上的AS号配置错,不是1234错误4:R2上配置的Key-chain的R4上配置的Key-chain不一致…...

判断完全数-第11届蓝桥杯省赛Python真题精选
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第27讲。 判断完全数&#…...

【Bootstrap5学习 day12】
Bootstrap5 导航 Bootstrap5提供了一种简单快捷的方法来创建基本导航,它提供了非常灵活和优雅的选项卡和Pills等组件。Bootstrap5的所有导航组件,包括选项卡和Pillss,都通过基本的.nav类共享相同的基本标记和样式。 创建基本导航 要创建简单…...

算法训练第五十九天|503. 下一个更大元素 II、42. 接雨水
503. 下一个更大元素 II: 题目链接 给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之…...

mysql之数据类型、建表以及约束
目录 一. CRUD 1.1 什么是crud 1.2 select(查询) 1.3 INSERT(新增) 1.4 UPDATE(修改) 1.5 DELETE(删除) 二. 函数 2.1 常见函数 2.2 流程控制函数 2.3聚合函数 三. union与union all 3.1 union 3.2 union all 3.3 具体不同 3.4 结论 四、思维导图 一. CRUD 1.1…...

复试 || 就业day04(2024.01.05)项目一
文章目录 前言线性回归房价预测加载数据数据查看数据拆分数据建模模型的验证、应用模型的评估 总结 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫本文内容来自某机构网课,是我为复试准备的第一个项目 &#…...
华为机试真题实战应用【赛题代码篇】-最小传输时延(附python、C++和JAVA代码实现)
目录 问题描述 输入描述: 输出描述: 知识储备 解题思路 思路一...
C++ 运算符重载
(Operator) 加分 减法 []的重载 #include <iostream> using namespace std;class time1 {public:time1(){shi0;fen0;miao0;}time1(int shi, int fen, int miao){this->shi shi;this->fen fen;this->miao miao;}time1 operator (ti…...

vue3学习 【2】vite起步和开发工具基本配置
vite的简介 官方文档 刚起步学习,所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18,可以参考上一篇文章的安装nvm,用来进行多版本的node管理。 vite安装与使用 npm create vitela…...

计算机创新协会冬令营——暴力枚举题目06
我给大家第一阶段的最后一道题就到这里了,下次得过段时间了。所以这道题简单一点。但是足够经典 下述题目描述和示例均来自力扣:两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target …...

单片机快速入门
参考连接: 安装MinGW-64(在win10上搭建C/C开发环境)https://zhuanlan.zhihu.com/p/85429160MinGW-64; 链接:https://pan.baidu.com/s/1oE1FmjyK7aJPnDC8vASmCg?pwdy1mz 提取码:y1mz --来自百度网盘超级会员V7的分享C…...
Eureka相关问题及答案(2024)
1、什么是Eureka? Eureka是一个由Netflix开发的服务发现(Service Discovery)工具,它是Spring Cloud生态系统中的一个关键组件。服务发现是微服务架构中的一个重要概念,它允许服务实例在启动时注册自己,以便…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...

结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...