线程上下文-ThreadLocal原理

ThreadLocal主要作用:为每个线程提供独立的变量副本,实现线程间的数据隔离,从而避免多线程环境下的资源共享冲突。

原理

ThreadLocal有个内部类 ThreadLocalMap,顾名思义是个Map结构:key为 ThreadLocal实例,value为线程私有数据。

每个Thread线程对象内部有 ThreadLocalMap 属性,用于存储线程本地变量

public class Thread implements Runnable {// ...ThreadLocal.ThreadLocalMap threadLocals = null;// 下文用到ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;// ...}

ThreadLocal每次使用都是直接调用get()、set()

ThreadLocalget()方法访问变量时,实际操作的是当前线程的ThreadLocalMap 属性。具体步骤如下:

  • 当前线程会首先查找自己的ThreadLocalMap
  • 如果找到对应的值,就返回这个值;如果没有找到,则会调用initialValue()方法来生成一个默认值,将ThreadLocalMapvalue对象返回。
public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);// 当前线程ThreadLocalMap若已初始化直接返回局部变量,// 未初始化则初始化后返回if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();
}

每个线程都会创建自己线程独立的ThreadLocalMap ,从而保证数据线程隔离。

内存泄漏ThreadLocalMap的键是弱引用,值不是,可能导致内存泄漏。使用后应调用remove()方法清理。

主、子线程ThreadLocal数据传递?

  1. 手动传递上下文
  2. InheritableThreadLocal可继承上下文,InheritableThreadLocal是ThreadLocal子类
  3. 线程池 TaskDecorator 装饰器,任务执行前后做一些事情(手动传递)
public class BusinessContextDecorator implements TaskDecorator {// 线程任务执行之前,把用户信息从主线程传递到子线程@Overridepublic Runnable decorate(Runnable runnable) {UserContextInfo userContext = UserContext.getUserContext();return () -> {try {UserContext.setUserContext(userContext);runnable.run();}finally {UserContext.clear();}};}
}
@Configuration
public class ThreadPoolExecutorConfig {private static final int CORE_THREAD_SIZE = Runtime.getRuntime().availableProcessors() + 1;private static final int MAX_THREAD_SIZE = Runtime.getRuntime().availableProcessors() * 2 + 1;private static final int WORK_QUEUE = 1000;private static final int KEEP_ALIVE_SECONDS = 60;@Bean("taskExecutor")public Executor taskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(CORE_THREAD_SIZE);executor.setMaxPoolSize(MAX_THREAD_SIZE);executor.setQueueCapacity(WORK_QUEUE);executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);executor.setThreadNamePrefix("task-thread-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());// 新增线程装饰器executor.setTaskDecorator(new BusinessContextDecorator());executor.initialize();return executor;}
}

父子数据传递

当创建一个新线程时,会调用Thread类的构造方法,在构造方法中会检查父线程的inheritableThreadLocals是否为空,如果不为空,则会将父线程的inheritableThreadLocals复制到子线程的inheritableThreadLocals中。

每个线程都有自己独立的inheritableThreadLocals实例,保证了线程间数据的隔离。

主子线程上下文隔离互不影响

public class InheritableThreadLocalExample {// 创建一个 InheritableThreadLocal 实例private static final InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();public static void main(String[] args) {// 在父线程中设置 InheritableThreadLocal 的值inheritableThreadLocal.set("Hello from parent thread");// 打印父线程中的值System.out.println("Parent thread value: " + inheritableThreadLocal.get());// 创建子线程Thread childThread = new Thread(() -> {// 打印子线程中继承的 InheritableThreadLocal 的值System.out.println("Child thread value: " + inheritableThreadLocal.get());// 在子线程中修改 InheritableThreadLocal 的值inheritableThreadLocal.set("Hello from child thread");System.out.println("Modified child thread value: " + inheritableThreadLocal.get());});// 启动子线程childThread.start();try {// 等待子线程执行完毕childThread.join();} catch (InterruptedException e) {e.printStackTrace();}// 打印父线程中的值,验证父线程的值不受子线程修改的影响System.out.println("Parent thread value after child thread modification: " + inheritableThreadLocal.get());// 清除 InheritableThreadLocal 的值inheritableThreadLocal.remove();}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15188.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】元组

个人主页&#xff1a;GUIQU. 归属专栏&#xff1a;Python 文章目录 1. 元组的本质与基础概念1.1 不可变序列的意义1.2 元组与数学概念的联系 2. 元组的创建方式详解2.1 标准创建形式2.2 单元素元组的特殊处理2.3 使用 tuple() 函数进行转换 3. 元组的基本操作深入剖析3.1 索引操…

SpringSecurity:授权服务器与客户端应用(入门案例)

文章目录 一、需求概述二、开发授权服务器1、pom依赖2、yml配置3、启动服务端 三、开发客户端应用1、pom依赖2、yml配置3、SecurityConfig4、接口5、测试 一、需求概述 maven需要3.6.0以上版本 二、开发授权服务器 1、pom依赖 <dependency><groupId>org.springfr…

android的Compose 简介

Jetpack Compose 简介 Jetpack Compose 是 Android 官方推出的声明式 UI 工具包&#xff0c;用于替代传统 XML 布局&#xff0c;简化界面开发流程。它基于 Kotlin 语言&#xff0c;通过函数式编程实现高效、灵活的 UI 构建&#xff0c;支持实时预览和更直观的状态管理。 优势…

四次挥手详解

文章目录 一、四次挥手各状态FIN_WAIT_1CLOSE_WAITFIN_WAIT_2LAST_ACKTIME_WAITCLOSE 二、双方同时调用close()&#xff0c;FIN_WAIT_1状态后进入CLOSING状态CLOSING状态 三、TIME_WAIT状态详解(1) TIME_WAIT状态下的2MSL是什么MSL &#xff08;报文最大生存时间&#xff09;为…

LIMO:上海交大的工作 “少即是多” LLM 推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型&#xff08;LLM&#xff09;中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据&#xff08;通常超过 100,000 个示例&#xff09;&#xff0c;但本文展…

51单片机之引脚图(详解)

8051单片机引脚分类与功能笔记 1. 电源引脚 VCC&#xff08;第40脚&#xff09;&#xff1a;接入5V电源&#xff0c;为单片机提供工作电压。GND&#xff08;第20脚&#xff09;&#xff1a;接地端&#xff0c;确保电路的电位参考点。 2.时钟引脚 XTAL1&#xff08;第19脚&a…

基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具&#xff0c;旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病&#xff0c;通常表现为认知障碍、记忆丧失和语言障碍等症状…

TAPEX:通过神经SQL执行器学习的表格预训练

摘要 近年来&#xff0c;语言模型预训练的进展通过利用大规模非结构化文本数据取得了巨大成功。然而&#xff0c;由于缺乏大规模高质量的表格数据&#xff0c;在结构化表格数据上应用预训练仍然是一个挑战。本文提出了TAPEX&#xff0c;通过在一个合成语料库上学习神经SQL执行…

轻松理解CSS中的float浮动元素

1.float:left&#xff0c;float:right可以让元素脱离原始文档流&#xff0c;也就是所谓的“浮动”&#xff0c;可以理解为元素漂浮在原本所占位置的上空&#xff0c;意思是元素漂浮起来了&#xff0c;不占原始文档流的空间。但是&#xff0c;别的元素可以感知到浮动元素的存在&…

Vue与Konva:解锁Canvas绘图的无限可能

前言 在现代Web开发中&#xff0c;动态、交互式的图形界面已成为提升用户体验的关键要素。Vue.js&#xff0c;作为一款轻量级且高效的前端框架&#xff0c;凭借其响应式数据绑定和组件化开发模式&#xff0c;赢得了众多开发者的青睐。而当Vue.js邂逅Konva.js&#xff0c;两者结…

【Git】tortoisegit使用配置

1. 安装 首先下载小乌龟&#xff0c;下载地址:https://tortoisegit.org/download/, 可以顺便下载语言包&#xff01; 安装时&#xff0c;默认安装就可以&#xff0c;一路next。也可以安装到指定目录中 目前已完成本地安装&#xff0c;接下来就需要与远程仓库建立连接&…

RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决

RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决 1、报错情况 下载&#xff1a;https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle 用idea打开&#xff0c;启动&#xff1a; 日志有报错&#xff1a; 点右侧m图标&#xff0c;maven有以下报误 &…

C++ 设计模式 - 访问者模式

一&#xff1a;概述 访问者模式将作用于对象层次结构的操作封装为一个对象&#xff0c;并使其能够在不修改对象层次结构的情况下定义新的操作。 《设计模式&#xff1a;可复用面向对象软件的基础》一书中的访问者模式因两个原因而具有传奇色彩&#xff1a;一是因为它的复杂性&a…

DeepSeek在FPGA/IC开发中的创新应用与未来潜力

随着人工智能技术的飞速发展&#xff0c;以DeepSeek为代表的大语言模型&#xff08;LLM&#xff09;正在逐步渗透到传统硬件开发领域。在FPGA&#xff08;现场可编程门阵列&#xff09;和IC&#xff08;集成电路&#xff09;开发这一技术密集型行业中&#xff0c;DeepSeek凭借其…

ZU47DR 100G光纤 高性能板卡

简介 2347DR是一款最大可提供8路ADC接收和8路DAC发射通道的高性能板卡。板卡选用高性价比的Xilinx的Zynq UltraScale RFSoC系列中XCZU47DR-FFVE1156作为处理芯片&#xff08;管脚可以兼容XCZU48DR-FFVE1156&#xff0c;主要差别在有无FEC&#xff08;信道纠错编解码&#xff0…

详解SQLAlchemy的函数relationship

在 SQLAlchemy 中&#xff0c;relationship 是一个非常重要的函数&#xff0c;用于定义模型之间的关系。它用于在 ORM 层面上表示数据库表之间的关联关系&#xff08;如 1 对 1、1 对多和多对多&#xff09;。relationship 的主要作用是提供一个高级接口&#xff0c;用于在模型…

【Matlab优化算法-第14期】基于智能优化算法的VMD信号去噪项目实践

基于智能优化算法的VMD信号去噪项目实践 一、前言 在信号处理领域&#xff0c;噪声去除是一个关键问题&#xff0c;尤其是在处理含有高斯白噪声的复杂信号时。变分模态分解&#xff08;VMD&#xff09;作为一种新兴的信号分解方法&#xff0c;因其能够自适应地分解信号而受到…

C++ 继承(1)

1.继承概念 我们平时有时候在写多个有内容重复的类的时候会很麻烦 比如我要写Student Teacher Staff 这三个类 里面都要包含 sex name age成员变量 唯一不同的可能有一个成员变量 但是这三个成员变量我要写三遍 太麻烦了 有没有好的方式呢&#xff1f; 有的 就是继承…

生成式聊天机器人 -- 基于Pytorch + Global Attention + 双向 GRU 实现的SeqToSeq模型 -- 下

生成式聊天机器人 -- 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 -- 下 训练Masked 损失单次训练过程迭代训练过程 测试贪心解码(Greedy decoding)算法实现对话函数 训练和测试模型完整代码 生成式聊天机器人 – 基于Pytorch Global Attention 双向 GRU 实…

《ARM64体系结构编程与实践》学习笔记(四)

MMU内存管理 1.MMU内存管理&#xff08;armv8.6手册的D5章节&#xff09;&#xff0c;MMU包含快表TLB&#xff0c;TLB是对页表的部分缓存&#xff0c;页表是存放在内存里面的。 AArch64仅仅支持Long Descriptor的页表格式&#xff0c;AArch32支持两种页表格式Armv7-A Short De…