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

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.kler.cn/news/340821.html

相关文章:

  • PostgreSQL中使用RETURNING子句来返回被影响行的数据
  • 力扣 二叉树 104. 二叉树的最大深度
  • FastJson详解与使用:高效JSON解析与序列化利器
  • 计算机毕业设计Django+Vue.js豆瓣图书推荐系统 图书评论情感分析 豆瓣图书可视化大屏 豆瓣图书爬虫 数据分析 图书大数据 大数据毕业设计 机器学习
  • 在Ubuntu 22.04上安装Ollama的两种方式
  • 胤娲科技:AI评估新纪元——LightEval引领透明化与定制化浪潮
  • Springboot3+druid+jasypt+application.yml配置文件数据库密码加密技术
  • 上门安装维修系统小程序开发详解及源码示例
  • pip 和 conda 的安装区别
  • Unity实现自定义图集(四)
  • 软件包与服务搭建
  • 滚雪球学Redis[3.1讲]:Redis的持久化机制
  • Scalable TCP 如何优化长肥管道
  • 《黑神话悟空:点燃朔州文旅之火》
  • 云服务器架构详解:X86计算_ARM_GPU/FPGA/ASIC_裸金属_超级计算集群
  • scrapy爬取汽车、车评数据【下】
  • 02. 上报自定义数据到 prometheus(使用 Python Client)
  • 【C++】set和multiset(关联式容器、键值对,set和multiset的基本特性、主要用途及常用操作)
  • 搜维尔科技:Haption远程操作项目模拟项目
  • Spring Validation —— 参数校验框架