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

java多线程环境下资源隔离机制ThreadLocal详解

背景

在我们实际业务开发过程中,会遇到这样的场景,需要在单个线程整个生命周期内部保存全局的数据信息,比如说:单个线程内部全局唯一数据库连接、唯一的日志记录id,线程用户信息等。
那么为什么不直接在线程内部采用局部变量呢?
这个涉及到线程内部方法调用传递参数比较麻烦,如果直接用Thread对象获取更加方便。

Thread线程对象

每个线程有自己独立的Thread对象

组成部分说明
虚拟机栈方法调用栈、局部变量表(线程私有)
本地方法栈执行 native 方法使用的栈(线程私有)
线程对象 Thread 本身每个线程创建时对应一个 Thread 实例
ThreadLocalMapThreadLocal 变量专属的存储空间(线程私有)
程序计数器(PC)当前执行的指令地址(线程私有)

ThreadLocalMap 的存储

Thread对象包含了一个私有变量
ThreadLocal.ThreadLocalMap threadLocals = null;
线程内部可以通过这个threadLocals成员属性拿到ThreadLocalMap,

ThreadLocalMap存储了什么呢?

他的每一个节点是一个Entry结构

static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}

这是什么意思呢?
就是相当于是一个键值对,他的key就是ThreadLocal对象,并且是弱引用,强引用就是我们在实际的方法栈中引用堆上的实例数据,弱引用是当JVM进行GC会回收掉他,前提是没有其他强引用。这样做是防止当前线程结束,线程回到了线程池,导致线程对象仍然间接引用着key,没有被垃圾回收,导致内存泄漏。
value值就是我们存储的数据值。

重要

key是弱引用,但是value是强引用,如果使用线程池,不释放,就会出现value内存泄漏,所以在线程结束时需要调用threadlocal的remove方法清楚数据。

threadLocalMap是一个Entry数组结构

  private Entry[] table;

每一个节点是一个ThreadLocal对象key,和一个值。

ThreadLocal对象

ThreadLocal对象是我们在代码中创建的存储数据的结构
例如:

	ThreadLocal local = new ThreadLocal();local.set(5);local.set(6);
ThreadLocal的set方法执行过程:
  1. 获取当前线程Thread对象的ThreadLocalMap实例对象
  2. 如果没有,null,那么就创建一个ThreadLocalMap,并且赋值给Thread对象的threadLocals
  3. 如果存在,就从ThreadLocalMap中获取到当前ThreadLocal对象为key的值,因为ThreadLocalMap是数组,就通过对ThreadLocal对象进行hash求知取到他的数组下标,如果这个下标不等于这个ThreadLocal对象,说明存在hash冲突,就通过开放寻址法,继续遍历下一个数组下标的元素,直到末尾。
  4. 找到之后,就可以设置value
  5. get方法也是一个逻辑

这样就达到了在多个线程中共享同一个ThreadLocal对象,互相操作对象内部的元素,但是又能实现资源的隔离

最后 吐槽一下

说实话,这种垃圾设计真的烧脑,引用链路复杂,晦涩难懂是正常人脑子能想出来的吗?简直是逆天
http://www.lryc.cn/news/584414.html

相关文章:

  • 【C++】红黑树的底层思想 and 大厂面试常问
  • Web前端:table标签的用法与属性
  • 学习日记-spring-day45-7.10
  • 二分查找篇——搜索旋转排序数组【LeetCode】一次二分查找
  • LFU 缓存
  • iOS APP混合开发性能测试怎么做?页面卡顿、通信异常的工具组合实战
  • iOS Widget 开发-7:TimelineProvider 机制全解析:构建未来时间线
  • 快速上手ASP .NET Core 8与MongoDB整合
  • Mac 电脑crontab执行定时任务【Python 实战】
  • 【保姆级喂饭教程】idea中安装Conventional Commit插件
  • Wsl/InstallDistro/Service/RegisterDistro/CreateVm/HCS/E_INVALIDARG
  • Android ViewBinding 使用与封装教程​​
  • Flutter 与 Android 的互通几种方式
  • 第35周—————糖尿病预测模型优化探索
  • 灰度发布过程中的异常处理
  • frp内网穿透下创建FTP(解决FTP“服务器回应不可路由的地址。使用服务器地址替代”错误)
  • Vue响应式原理五:响应式-自动收集依赖
  • 【Action帧简要分析】
  • 实验作业1+整理笔记截图
  • LLM 微调:从数据到部署的全流程实践与经验分享
  • TradePort 借助 Walrus 构建更高级的 NFT 市场
  • FPGA设计思想与验证方法学系列学习笔记001
  • 基于“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展应用
  • upload-labs靶场通关详解:第20关 /.绕过
  • 【计算机网络】HTTP1.0 HTTP1.1 HTTP2.0 QUIC HTTP3 究极总结
  • QT解析文本框数据——概述
  • 中国成人急性髓系白血病(非M3)诊疗指南(2021年版)
  • upload-labs靶场通关详解:第21关 数组绕过
  • Mysql分片:一致性哈希算法
  • 【Python】基于Python提取图片验证码