ThreadLocal

关系

一个Thread对应一个ThreadLocalMap,一个ThreadLocalMap可保存多个ThreadLocal为键的键值对,值为需要线程共享的数据,而且多个线程可共用一个ThreadLocal对象,在web项目中多有这样的设计。

源码分析

Thread中有一个ThreadLocalMap类型的属性threadlocals,ThreadLocalMap是ThreadLocal的一个内部类。

1.ThreadLocal的set方法




先获取当前线程t,再执行getMap(t)



其实就是获取t.threadLocals,若此时getMap(t)为空,则执行createMap(this,value)



若为空,则创建ThreadMap对象并给当前Thread的threadLocals属性赋值,并在ThreadLocalMap中放入一对键值对,其中键为当前调用方法的ThreaadLocal对象(this),值为set方法传入的value。
若非空,则直接在该线程对应的ThreadLocalMap中放入该键值对即可。

2.ThreadLocal的get方法




与set方法类似,先获取当前Thread对应的ThreadLocalMap,再通过ThreadLocal实例(this)获取所需值。

3.remove方法

4.ThreadLocal的并发性

由于每一个ThreadLocal都对应了一个ThreadLocalMap,也就是说每一个线程都持有一份数据副本,也就不存在数据的并发操作。
Thread中还有一个ThreadLocalMap类型的属性inheritableThreadLocals。在new Thread()时,在构造方法里会把父线程中的inheritableThreadLocals的ThreadLocalMap内容复制给当前子线程的inheritableThreadLocals,也就是说子线程会继承父线程中的inheritableThreadLocals对应的ThreadLocalMap,而且是复制一份,子线程中的ThreadLocalMap和父线程中的ThreadLocalMap中的内容一开始是一样的,但是后续的修改将互不影响。

5.ThreadLocal的内存泄漏问题

ThreadLocaMap中,key对ThreadLocal的引用时弱引用。


5.1 为什么要对ThreadLocal使用弱引用?

因为ThreadLocal就是做同线程数据共享的,若ThreadLocal中不存在对象引用时,ThreadLocal也应该被回收,而由于设计的引用链,Thread引用ThreadLocalMap,ThreadLocalMap中的key又引用ThreadLocal,使得ThreadLocal不会被回收。而弱引用的特点为当对象只有弱引用存在时,该对象可以被gc回收。所以对Thread Local使用弱引用能解决此问题。

5.2 引发的内存泄漏问题

ThreadLocal为弱引用,这样就会导致ThreadLocalMap.Entry的key为null,而value是强引用,那么会导致value引用的对象只有在Thread销毁时才会被释放,ThreadLocalMap中也永远存在一个value非空的永远不会被访问到的Entry,引发了内存的泄漏。

5.3 线程安全问题

Tomcat会维护一个线程池,若不同的请求使用的相同的线程,有可能会出现访问到之前的信息,从而引发安全问题。

解决方法

程序员手动执行remove方法。

5.4 为什么不把value设置为弱引用?

避免外部持有key的引用来查询value,而value却被回收的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值