ThreadLocal

是什么

ThreadLocal提供线程局部变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。ThreadLocal实例通常是类中的私有静态字段。 T h r e a d L o c a l 并 不 解 决 线 程 间 共 享 数 据 的 问 题 。 \color{#FF0000}{ThreadLocal 并不解决线程间共享数据的问题。} ThreadLocal线

使用场景

ThreadLocal 适用于变量在线程间隔离且在方法间共享的场景。

场景一:代替参数的显式传递

当我们在写API接口的时候,通常Controller层会接受来自前端的入参,当这个接口功能比较复杂的时候,可能我们调用的Service层内部还调用了 很多其他的很多方法,通常情况下,我们会在每个调用的方法上加上需要传递的参数。

但是如果我们将参数存入ThreadLocal中,那么就不用显式的传递参数了,而是只需要ThreadLocal中获取即可。

这个场景其实使用的比较少,一方面显式传参比较容易理解,另一方面我们可以将多个参数封装为对象去传递。

场景二:全局存储用户信息

在拦截器中获取到用户信息然后存入ThreadLocal,当前线程在任何地方如果需要拿到用户信息都可以使用ThreadLocal的get()方法 (异步程序中ThreadLocal是不可靠的)。

场景三:解决线程安全问题

ThreadLocal在设计之初就是为解决并发问题而提供一种方案,每个线程维护一份自己的数据,达到线程隔离的效果。

Thread,ThreadLocal,ThreadLocalMap,Entry 关系

​ ThreadLocal连接了Thread和ThreadLocalMap (Thread.java里面有一个变量),ThreadLocalMap 是ThreadLocal的静态内部类,ThreadLocalMap又有一个静态内部类Entry。Entry的key为ThreadLocal的弱引用,v为value。

在这里插入图片描述

在这里插入图片描述

ThreadLocal内存泄露

内存泄漏原因
	1. 当我们为threadLocal变量赋值,通过Thread,ThreadLocal,ThreadLocalMap,Entry 关系知道,实际上是存放在Entry中的,如果线程使用完ThreadLocal后不进行remove(),那么Entry中的key依然有它的引用(是弱引用,就是防止用户忘了remove(),这算是防止内存泄漏的一种保护措施),这将有可能导致内存泄漏。而且在线程复用(线程池)的情况下忘记remove()还有可能导致数据污染出现功能错误。
	2. 由于Entry中的key是弱引用,(tl=null),那么系统 GC 的时候,根据可达性分析,这个threadLocal实例就没有任何一条链路能够引用到它,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
解决方法
  1. ThreadLocalMap的Entry中key对ThreadLocal的引用为弱引用,只要系统进行GC就可以回收,避免了用户不手动调用remove()方法造成的内存泄漏。
  2. 都会通过expungeStaleEntry,cleanSomeSlots,replaceStaleEntry这三个方法回收键为 null 的 Entry 对象的值(即为具体实例)以及 Entry 对象本身从而防止内存泄漏,属于安全加固的方法

阿里手册相关

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值