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生态系统中的一个关键组件。服务发现是微服务架构中的一个重要概念,它允许服务实例在启动时注册自己,以便…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
