static能不能修饰threadLocal,为什么

题目来源:https://zhuanlan.zhihu.com/p/86536581
java面试清单
**java基础 **
详解

static能不能修饰threadLocal,为什么
static可以用来修饰threadlocal。经过static修饰的变量,在类加载时候就完成了内存的分配和初始化,在内存中只有一个副本,被所有对象共享。
可以避免重复创建线程相关的变量(TSO)。我们知道一个ThreadLocal实例,对应当前线程中的一个TSO。因此,如果把Threalocal申明为某一个类的实例变量,那么每创建一个该类的实例就会导致一个新的TSO实例被创建。显然那,这个被创建的TSO是一个类的实例。于是,同一个线程可能会访问到同一个TSO额不同是列,这会导致浪费。因此使用static修饰。

ThreadLocal是什么?
ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发的场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的变量值完成操作的场景。
ThreadLocal为变量在每个线程内创建了自己的副本,每个线程可以访问自己内部的副本变量。
ThreadLocal适用场景
当改变变量属于:一个线程不需要关心其他线程是否对这个变量进行了修改时,使用ThreadLocal
ThreadLocal的核心机制
1 每一个Thread线程里面都有一个Map
2 Map里面存储是线程本地对象(key)和线程的变量副本(value)
3 但是,Thread线程内部的Map,由ThreadLocal进行维护,由ThreadLocal负责对Map进行获取和设置线程的变量值
所以对于不同的线程,每次获取副本值时,别的线程并不能获取当前线程的副本值,形成了副本隔离,互不干扰
深入理解ThreadLocal
ThreadLocalMap是ThreadLocal的内部实现类,没有实现Map接口,用独立的方式实现了Map的功能,其内部的Entry也独立实现。
<key, value>====<ThreadLocal对象, 变量副本值>
Hahs冲突如何解决
首先,hash冲突出现在将ThreadLocal对象映射为key时,有可能会造成冲突
其次,假如冲突发生如何解决?
ThreadLocalMap中解决Hash的方法并非链表式,而是采用线性探测的方法。因此在ThreadLocalMap中结构很简单。
所谓线性探测,就是根据初始key的hashcode值确定元素在table中的位置,如果发现该位置已经被占用,则利用固定的算法寻找一顶步长的下一个位置,一次判断,直到能够找到能够存放的位置。
ThreadLocalMap的内存泄漏问题
由于在ThreadLocalMap中的key是弱引用,而value是强引用。这就导致了一个问题,当ThreadLocal在没有外部强引用时,发生GC时弱引用key会被回收掉,而value不会被回收。如果创建的Threadlocal的线程一直在运行,那么这个Entry对象中的value就一直得不到回收,发生内存泄漏。
如何避免ThreadlocalMap的内存泄漏
在调用Threadlocal中的get() set()方法之后,在调用remove()方法将Entry结点和Map的引用关系移除,这个整个Entry对象在GC roots分析以后,就变成不可达,下次GC的时候,就会被回收。
总结

每个ThreadLocal只能保存一个变量副本,如果想要上线一个线程能够保存多个副本以上,就需要创建多个ThreadLocal。
ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险。
适用于无状态,副本变量独立后不影响业务逻辑的高并发场景。如果如果业务逻辑强依赖于副本变量,则不适合用ThreadLocal解决,需要另寻解决方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值