当前位置: 首页 > 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.dtcms.com/a/272607.html

相关文章:

  • C#内插字符串:从语法糖到深度优化
  • 学习笔记(32):matplotlib绘制简单图表-数据分布图
  • 入门级别的Transformer模型介绍
  • Rust中Option和Result详解
  • 微调性能赶不上提示工程怎么办?Can Gradient Descent Simulate Prompting?——论文阅读笔记
  • Apache Shiro 框架详解
  • 【三维生成】FlashDreamer:基于扩散模型的单目图像到3D场景
  • Express 入门指南(超详细教程)
  • 机器学习之逻辑回归和k-means算法(六)
  • 32多串300A保护板测试仪:新能源电池安全的核心守护者
  • 生成式人工智能实战 | 自注意力生成对抗网络(Self-Attention Generative Adversarial Network, SAGAN)
  • 深入理解fork():系统调用创建进程的原理与实践
  • 项目部署:nginx的安装和配置
  • 利用Pandas进行条件替换与向前填充
  • Linux中的命令连接符
  • Layui —— select
  • 图解Java数据容器(三):Queue
  • CAS登录工作流程简述
  • 【前端】【Echarts】ECharts 词云图(WordCloud)教学详解
  • Prompt提示词的主要类型和核心原则
  • 在vscode中和obsidian中使用Mermaid
  • Spring AI Alibaba(2)——通过Graph实现工作流
  • Flutter 与 Android 的互通几种方式
  • Linux 中 sed 命令
  • RedisJSON 路径语法深度解析与实战
  • Spring Boot + Javacv-platform:解锁音视频处理的多元场景
  • 【TCP/IP】12. 文件传输协议
  • MySQL索引操作全指南:创建、查看、优化
  • Debian-10编译安装Mysql-5.7.44 笔记250706
  • macOS 上安装 Miniconda + Conda-Forge