ThreadLocal

ThreadLocal是什么?

Threadlocal是线程变量

每个Thread线程内部都有一个Map。
Map里面存储线程本地对象(key)和线程的变量副本(value)
但是,Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。由threadlocal生成hashcode定位数组位置

Threadlocal示意图.png

ThreadLocal作用?

ThreadLocal的作用主要是做数据隔离,填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的

1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。

2、线程间数据隔离

3、进行事务操作,用于存储线程事务信息。

4、数据库连接,Session会话管理。

ThreadLocal hash冲突

ThreadLocal采用散列表存储数据,这样不可避免的存在hash冲突,当存在hash冲突时,threadLocal主要采取线性探测法(如果该entry哈希后对应的位置以及存在了值,则继续找寻下一个位置)

线性探测法其实存在很大问题。当散列表中插入的数据越来越多时,散列冲突发生的可能性就会越来越大,空闲位置会越来越少,线性探测的时间就会越来越久。极端情况下,我们可能需要探测整个散列表,所以最坏情况下的时间复杂度为 O(n) 。同理,在删除和查找时,也有可能会线性探测整张散列表,才能找到要查找或者删除的数据

ThreadLocal的内存泄露

thradLocal在保存对象是会把对象保存在ThreadLocalMap中,threadLocalmap的key 被设置为弱引用,弱引用对象当jvm启动gc时该对象只有弱引用,则他会被垃圾收集器清除。当ThreadLocal没有其他外部引用时,ThreadLocalMap中的key就会被清除,当创建Thradlocal线程没有释放时(比如线程池)。导致ThreadLocalMap中value没有被释放。ThreadLocalMap中存在很多key为空,value为某个对象的entry,最终导致内存溢出。

解决方法:在线程调用结束后调用ThreadLocal.remove()方法。

为什么 ThreadLocalMap 的 key 是弱引用?

如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。

你可能感兴趣的:(ThreadLocal)