ThreadLocal 是 Java 中的一个类,用于实现线程封闭(Thread-local)的数据存储机制。每个线程都有自己的 ThreadLocalMap,其中 ThreadLocal 对象充当键,线程的变量副本作为对应键的值。使用 ThreadLocal 的 set() 方法将数据存储在当前线程的 ThreadLocalMap 中,而使用 get() 方法则是从当前线程的 ThreadLocalMap 中获取数据副本。
这种机制为每个线程维护独立的变量副本,这样可以实现线程之间的数据隔离,从而有效地避免了线程安全问题。这对于需要在线程内部存储线程特定数据的情况非常有用,例如数据库连接、用户会话信息等。但需要谨慎使用 ThreadLocal,确保在不再需要时及时清理变量副本,以避免潜在的内存泄漏问题。这种机制提供了一种有效的方式来确保线程级别的数据隔离和线程安全性。
关键字
ThreadLocalMap
维护的 threadLocals 数组
内部的Hash表(开放定址法)
单独实现的一个hashtable,使用数据的方式,开放探测的方法解决hash冲突
探测式清理:
探测式清理是以当前Entry 往后清理,遇到值为null则结束清理,属于线性探测清理。
启发式清理:
从当前节点开始,进行do-while循环检查清理过期key,结束条件是连续n次未发现过期key就跳出循环,n是经过位运算计算得出的,可以简单理解为数组长度的2的多少次幂 次,
扩容逻辑:
大于 3/4 的容量,就扩容
创建新数组,迁移完毕后,就更新 table 的指向
ThreadLocal 与InheritableThreadLocal
ThreadLocal:子线程无法共享父线程的本地变量
InheritableThreadLocal:子线程可以共享父线程的本地变量,在创建线程的时候:new Thread() 的时候,但是在线程池中,无法很好的支持
仅共享初始值
内部类Entry设置为WeakReference的原因,是为了当用户使用完ThreadLocal后,将Threadlocal变量设置为null后,GC能够回收掉ThreahlocalMap中的空间
2.1 为什么ThreadLocal的key要使用弱引用?
线程池的情况下,可能一直无法回收 key 对应的内存
🐸 ThreadLocalMap 是线程的成员变量,只要线程还未结束,则会一直被Thread强引用着,假设 Entry 对象的 key 是对 ThreadLocal 对象的强引用,如果在其他地方都没有对这个 ThreadLocla 对象的引用了,然后在使用ThreadLocalMap的过程中又没有正确地在用完后就调用 remove 方法,所以这个 ThreadLocal 对象和所关联的 value 对象就会跟随着线程一直存在,这样可能会造成OOM。
2.2 为什么ThreadLocal的value不能使用弱引用?
避免获取到的值为 null,引起逻辑异常
🐸【假设Entry 的 value 是弱引用】:假设 key 所引用的 ThreadLocal 对象还被其他的引用对象强引用着,那么这个 ThreadLocal 对象就不会被 GC 回收,但如果 value 是弱引用且不被其他引用对象引用着,那 GC 的时候就被回收掉了,那线程通过 ThreadLocal 来获取 value 的时候就会获得 null,对我们来说,value 才是我们想要保存的数据,ThreadLcoal 只是用来关联 value 的,如果 value 都没了,还要 ThreadLocal 干嘛呢?所以 value 不能是弱引用。
使用场景:
1、链路监控,如阿里内部的鹰眼
2、分布式链路的日志记录
3、通用的登录功能
缺点:
1、没有权限控制
2、有内存泄露风险
JDK21替代品:ScopedValue
优点:
有生命周期
有作用域
阿里巴巴的开源组件:TransmittableThreadLocal
原理:
1、有一个static final InheritableThreadLocal 的holder,value是一个WeakHashMap
map的key 是 TransmittableThreadLocal ,value是 具体的对象
2、线程池,使用自己的方法,包了一层,在run的时候,会做一些操作,将InheritableThreadLocal的值进行传递
参考文档:
1、https://juejin.cn/post/6844904151567040519#heading-15
2、ThreadLocal为什么使用弱应用
https://zhuanlan.zhihu.com/p/304240519?utm_id=0
3、https://zhuanlan.zhihu.com/p/402856377
4、ScopedValue:https://juejin.cn/post/7287241480770928655
5、https://www.cnblogs.com/lihw/p/17214194.html
6、TransmittableThreadLocal