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

ThreadLocal底层原理及数据结构详解

  ThreadLocal允许为每个线程创建独立的变量副本,使得同一个ThreadLocal对象在不同的线程中拥有不同的值。它的主要作用是在并发环境下提供线程隔离,避免多个线程共享同一个变量,从而减少线程间的相互干扰。

  ThreadLocal的核心在于为每个线程维护一个独立的数据副本,它的实现主要依赖于每个线程维护一个ThreadLocalMap,这是ThreadLocal专用的Map,用来存储线程自己的变量。

1.1. ThreadLocalMap底层数据结构

  ThreadLocalMap是一个定制化的Map,其结构类似于HashMap,都是以Key-Value的键值对形式进行存储,其中Key存储的是ThreadLocal实例Value存储的是对应的对象,默认为Object。相比于HashMap有一些不同之处:

  • 弱引用的键:ThreadLocalMap的键(即ThreadLocal对象)使用了弱引用(强引用>软引用>弱应用>虚引用),因此当没有其他地方引用该ThreadLocal对象时,GC就会回收它。
  • 线性探测解决哈希冲突:区别于HashMap中的链地址法解决哈希冲突,ThreadLocalMap使用线性探测法来解决哈希冲突,并且负载因子为2/3。
  • 潜在内存泄漏:由于ThreadLocalMap中的键是弱引用,但其存储的Value是强应用,如果ThreadLocal对象被GC回收,而没有调用remove()方法清理值,那么ThreadLocalMap中的值就有可能会一直存在,导致内存泄漏。因此在不适用ThreadLocal后,要及时的调用remove()方法,手动清除线程的副本变量。或者使用 try-finally 模式来保证在完成工作后调用 remove()
1.2. 能否使用ThreadLocal往线程中存储多个副本变量?

         默认情况下,ThreadLocal每个线程只能存储一个值,因为它的设计初衷就是让每个线程独立的维护一组与ThreadLocal对象相关的值,也就是说,每个ThreadLocal实例只能存储一个值。

        虽然 ThreadLocal 本身每个实例只能存储一个值,但多个 ThreadLocal 实例在同一个线程中是存储在 ThreadLocalMap 里的。因此,当一个线程中存在多个 ThreadLocal 实例时,这些实例及其对应的值就会存储在该线程的 ThreadLocalMap 中。

        那如果我们就是想让一个线程拥有多个副本变量该怎么办?

  • 法一:使用ThreadLocal存储一个容器(如Map或自定义对象)

        虽然每个ThreadLocal实例只能存储一个值,但是其存储的是什么值是由我们决定的,因此可以将想要存储的多个变量放入Map中,以此实现存储多个独立的副本变量。

  • 法二:使用多个ThreadLocal对象
private static ThreadLocal<String> threadLocal1 = new ThreadLocal<>();
private static ThreadLocal<Integer> threadLocal2 = new ThreadLocal<>();
threadLocal1.set("Thread1");
threadLocal2.set("Thread2");

        通过以上代码在每个线程的ThreadLocalMap中创建了两个ThreadLocal对象,分别存储"Thread1"和"Thread2",因此可以通过不同的ThreadLocal实例对象来获取不同的值。

http://www.lryc.cn/news/453836.html

相关文章:

  • Android Framework AMS(02)AMS启动及相关初始化5-8
  • 速盾:游戏被攻击怎么办?
  • BUU刷题-Pwn-shanghai2018_baby_arm(ARM_ROP_csu_init,ARM架构入门)
  • flutter_鸿蒙next(win)环境搭建
  • 腾讯一面-LRU缓存
  • k8s实战-1
  • Python进程池:提升你的并发性能
  • 内存占用估算方法
  • 拓扑排序简介
  • 使用iTextPDF库时,设置文字为中文格式
  • Windows环境下使用Docker配置MySQL数据库
  • 快速上手C语言【上】(非常详细!!!)
  • [深度学习][python]yolov11+deepsort+pyqt5实现目标追踪
  • 【CSDN入门级教程】
  • 二叉搜索树 (BST) 节点插入、查找、删除、获取最大值、最小值和中序遍历排序等功能
  • unity ps 2d animation 蛇的制作
  • 39 C 语言枚举类型、枚举常量、枚举变量、枚举的遍历、枚举数组、枚举与 switch
  • LabVIEW程序怎么解决 Bug?
  • AR智能眼镜之战:Meta vs Snap
  • Spring Boot 集成 Flowable UI 实现请假流程 Demo
  • 毕业设计选题:基于ssm+vue+uniapp的医院管理系统小程序
  • 自动驾驶系列—线控悬架技术:自动驾驶背后的动力学掌控者
  • CTF刷题buuctf
  • Qt QWidget控件
  • 如何通过Dockfile更改docker中ubuntu的apt源
  • [C++][第三方库][jsoncpp]详细讲解
  • JavaScript中decodeURIComponent函数的深入解析与应用指南
  • DMA方式为什么无需保护现场
  • 区块链可投会议CCF C--FC 2025 截止10.8 附录用率
  • springboot系列--web相关知识探索四