当前位置: 首页 > news >正文

线程上下文-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.mrgr.cn/news/90065.html

相关文章:

  • 【JAVA使用Aes加密报错:Illegal key size or default parameters,如何解决?】
  • 查询已经运行的 Docker 容器启动命令
  • 【python】matplotlib(animation)
  • android的Jetpack简介
  • 安装perl-DBD-MySQL报错:Requires: libmysqlclient.so.18
  • Breakout靶场小试牛刀
  • 百度高德地图坐标转换
  • 网络防御高级02-综合实验
  • vue学习5
  • win10 llamafactory模型微调相关① || Ollama运行微调模型
  • 网络计算机的相关概念整理
  • FreeRTOS实战项目——STM32F103ZET6智能门禁系统(二)
  • 活动预告 |【Part 2】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁
  • JavaScript中的防抖与节流:提升性能的关键技巧
  • 保姆级教程Docker部署Zookeeper官方镜像
  • 第3章 城市隧道工程与城市轨道交通工程 3.2 地下水控制
  • 【AIGC】DeepSeek本地部署方法详解:基于Ollama与LM-Studio
  • deepseek+kimi自动生成ppt
  • 策略模式(Strategy)
  • react 路由配置:从入门到精通
  • 解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用
  • 区块链技术未来发展趋势(人工智能和物联网领域)
  • 【计算机网络】TCP/IP 网络模型有哪几层?
  • 寒假集训思维训练1题解
  • [Meet DeepSeek] 如何顺畅使用DeepSeek?告别【服务器繁忙,请稍后再试。】
  • deepseek v3网络结构源码分析笔记