threadlocal是什么
每个线程所拥有的私有存储空间,线程间不可访问对方的存储空间。
threadlocal怎么用
是一个以 ThreadLocal 对象为键、任意对象为值的存储结构
ThreadLocal 类常用方法,如下:
protected T initialValue():设置初始值,默认为null
public void set(T value):设置一个要保存的值,并会覆盖原来的值
public T get():获得保存的值,如果没有用过set方法,会获取到初始值
public void remove():移除保存的值
threadlocal需要注意
1. 在线程池中使用
线程池中的线程是可以复用的。每个request请求可复用线程,在复用情况下,若往线程中存入值,复用后的线程中也能拿到值。
存在的问题:
你在某个线程中 threadlocal存入了值any,则通过这个any判断不走某逻辑A。多次request请求,这多次都未存入any值,可还是没走某逻辑A。问题出在多次request请求时,其他有复用了之前的线程,之前线程存入了any值。
解决方案:
每次存入值any后,并进行不走逻辑A后,进行清理any值。通过调用remove()方法。
也可看例子:https://www.jianshu.com/p/53f0a5935205
2. 内存泄露问题
request和ThreadLocal的差别
1)存取值方式不同。
request根据KEY存取值、一个request可以存多个值。
ThreadLocal只能存一个值,ThreadLocal的get和set方法没有参数KEY。
2)使用地方不一样。
request使用在表示层、一般在Action和Servlet中使用。
ThreadLocal在什么地方都可以、一般用在框架基类中比较多、比如存放当前的数据库连接等。
ThreadLocal的设计是‘空间换时间’,synchronized顺序执行是‘时间换取空间’(抛出问题:synchronized与CAS)
threadlocal存储分析:
图片来着:https://zhuanlan.zhihu.com/p/58636499
1.为什么ThreadLocalMap使用弱引用存储ThreadLocal?
假如使用强引用,当ThreadLocal不再使用需要回收时,发现某个线程中ThreadLocalMap存在该ThreadLocal的强引用,无法回收,造成内存泄漏。
因此,使用弱引用可以防止长期存在的线程(通常使用了线程池)导致ThreadLocal无法回收造成内存泄漏。
2.那通常说的ThreadLocal内存泄漏是如何引起的呢?
我们注意到Entry对象中,虽然Key(ThreadLocal)是通过弱引用引入的,但是value即变量值本身是通过强引用引入。
这就导致,假如不作任何处理,由于ThreadLocalMap和线程的生命周期是一致的,当线程资源长期不释放,即使ThreadLocal本身由于弱引用机制已经回收掉了,但value还是驻留在线程的ThreadLocalMap的Entry中。即存在key为null,但value却有值的无效Entry。导致内存泄漏。
但实际上,ThreadLocal内部已经为我们做了一定的防止内存泄漏的工作。
来着:https://segmentfault.com/a/1190000020914820
抛出问题:
1. threadlocal为什么要定义成static 、final?
定义成 final 就是为了不能改变。ThreadLocal 就像是一个盒子,大家都可以放取东西。但盒子不能换掉,不然放进去的东西一下子就没了。。。
https://bbs.csdn.net/topics/300229985
2. threadlocal为什么设置key为弱引用?
内存泄漏的真正原因是当前线程持有了Map,导致Map和当前线程的生命周期一样。而不是因为弱引用,弱引用的目的是让key的生命周期不跟着当前线程,减小内存泄露的风险。
3. 如何避免threadloacal内存溢出?