首页 > 其他分享 >ThreadLocal 详解

ThreadLocal 详解

时间:2023-08-18 20:58:17浏览次数:32  
标签:ThreadLocalMap get 回收 ThreadLocal 详解 引用 key

ThreadLocal中ThreadLocalMap的数据结构?

Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap

ThreadLocalMap有自己的独立实现,可以简单地将它的key视作ThreadLocalvalue为代码中放入的值(实际上key并不是ThreadLocal本身,而是它的一个弱引用)。

每个线程在往ThreadLocal里放值的时候,都会往自己的ThreadLocalMap里存,读也是以ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离

ThreadLocalMap有点类似HashMap的结构,只是HashMap是由数组+链表实现的,而ThreadLocalMap中并没有链表结构。

我们还要注意Entry, 它的keyThreadLocal<?> k ,继承自WeakReference, 也就是我们常说的弱引用类型。

ThreadLocal的 key 是弱引用,那么在 ThreadLocal.get()的时候,发生GC之后,key 是否为null?

为了搞清楚这个问题,我们需要搞清楚Java四种引用类型

  • 强引用:我们常常 new 出来的对象就是强引用类型,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候
  • 软引用:使用 SoftReference 修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收
  • 弱引用:使用 WeakReference 修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收
  • 虚引用:虚引用是最弱的引用,在 Java 中使用 PhantomReference 进行定义。虚引用中唯一的作用就是用队列接收对象即将死亡的通知

这个问题刚开始看,如果没有过多思考,弱引用,还有垃圾回收,那么肯定会觉得是null,其实是不对的,我们在做 ThreadLocal.get() 操作,证明其实还是有强引用存在的,所以 key 并不为 null,如果我们的强引用不存在的话,那么 key 就会被回收,也就是会出现我们 value 没被回收,key 被回收,导致 value 永远存在,出现内存泄漏。

 

ThreadLocalMap.get()详解

上面已经看完了set()方法的源码,其中包括set数据、清理数据、优化数据桶的位置等操作,接着看看get()操作的原理。

# ThreadLocalMap.get()图解

第一种情况: 通过查找key值计算出散列表中slot位置,然后该slot位置中的Entry.key和查找的key一致,则直接返回:

 

第二种情况: slot位置中的Entry.key和要查找的key不一致:

 

我们以get(ThreadLocal1)为例,通过hash计算后,正确的slot位置应该是 4,而index=4的槽位已经有了数据,且key值不等于ThreadLocal1,所以需要继续往后迭代查找。

迭代到index=5的数据时,此时Entry.key=null,触发一次探测式数据回收操作,执行expungeStaleEntry()方法,执行完后,index 5,8的数据都会被回收,而index 6,7的数据都会前移。index 6,7前移之后,继续从 index=5 往后迭代,于是就在 index=5 找到了key值相等的Entry数据,如下图所示:

 

# ThreadLocalMap.get()源码详解

 java.lang.ThreadLocal.ThreadLocalMap.getEntry():

 


 

标签:ThreadLocalMap,get,回收,ThreadLocal,详解,引用,key
From: https://www.cnblogs.com/szza/p/17641569.html

相关文章

  • Threadlocal
    一:Threadlocal的key是弱引用,那么在Threadlocal.get()的时候,发生GC之后,key否为nul!?答:在ThreadLocal中,key是使用弱引用的。在执行ThreadLocal.get()方法时,如果发生了垃圾回收(GC),对应的key会自动被回收,并在下一次ThreadLocal操作时被剔除 二:ThreadLocal中ThreadLocalMap的数据......
  • thingsboard gateway mqtt 连接详解
    mqtt的配置可见官网说明:https://thingsboard.io/docs/iot-gateway/config/mqtt/ 这里主要从源码说一下tbgateway里,mqttconnector的启动过程,和mqttconnector怎么工作  mqttconnector实现消息处理,主要在几个回调方法上,下面就主要方法说明:   接收消息后,就是处理......
  • ThreadLocal的作用以及其存在的问题
    ThreadLocal是JDK自带的一个类,他的作用是为每个线程中创建专属本地变量,这些变量只能被当前线程访问和修改,其他线程无法访问,当你创建了一个ThreadLocal里的变量后,每个访问这个变量的线程都会获得一个此变量的本地副本,同时THreadLocal提供了get()、set()方法来获取默认值,或将其值更......
  • Optional详解
    1.介绍Optional是Java8引入的一个新的类,它是java.util包下面的一个类。主要目的是为了解决空指针异常问题,它既可以含有对象也可以为空。2.Optional的使用2.1:创建一个Optional如果需要创建一个空的Optional的话,则可以使用Optional的empty()方法。empty方法的代码为:publicsta......
  • 技术分享| WebRTC之SDP详解
    一,什么是SDPWebRTC是WebReal-TimeCommunication,即网页实时通信的缩写,是RTC协议的一种Web实现,项目由Google开源,并和IETF和W3C制定了行业标准。WebRTC是点对点通讯,他的通话建立需要交换媒体信息才能建立,媒体信息的载体就是SDP。SDP(SessionDescriptionProtocol)是......
  • 融媒行业落地客户旅程编排,详解数字化用户运营实战
    移动互联网时代是流量红利的时代,企业常用低成本的方式进行获客,“增长黑客”的概念大范围传播。与此同时,机构媒体受到传播环境的影响,也开始启动全行业的媒体融合转型。在此背景下,2015年神策数据成立,核心解决的是帮助客户通过数据分析实现更好的增长。2020年之后数字化转型的大趋势......
  • 软件测试|Linux三剑客之grep命令详解
    简介grep是一款在Linux和类Unix系统中广泛使用的文本搜索工具。它的名字来源于GlobalRegularExpressionPrint(全局正则表达式打印),它的主要功能是根据指定的模式(正则表达式)在文本文件中搜索并打印匹配的行。grep非常强大且灵活,可以用于日志分析、文件过滤、代码搜索等多种场......
  • 软件测试|Linux三剑客之sed命令详解
    简介sed(StreamEditor)是一款流式文本编辑器,在Linux和类Unix系统中广泛使用。它的设计目的是用于对文本进行处理和转换,可以用于替换、删除、插入、打印等操作。sed命令通过逐行处理文本,允许您使用简单的命令来编辑大量文本数据。本文将详细介绍sed命令的基本用法和一些常见的......
  • 鸿蒙万能卡片开发详解-记忆翻牌游戏
    (目录)1.前言      翻牌游戏万能卡片,随机生成16张共包含8张完全不同的图像,游戏的目标是在有限30秒时间内,将16张卡片中包含相同的图像的卡片两两配对。匹配的规则是连续点击两张卡片,若卡背面的图像相同,则匹配成功,若不同则配对失败。游戏主要考察玩家的记忆力,因为游戏还规定......
  • JS数据类型详解
    JS的数据类型分为基本数据类型+引用数据类型基本数据类型:number,boolean,string,null,undefined, symbol(独一无二并且不可变的数据类型),bigint引用数据类型: Function,Array,Object区别:基本数据类型由于所占内存大小可控所以放于栈中,引用数据类型所占空间不固定放于堆中,并生......