为什么TheadLocalMap设计成一个个entry对象,而不用hashMap?

1、在设计ThreadLocal时,参考jdk都是鉴于效率性能优先。ThreadLocalMap对ThreadLocal场景做了优化,这些场景是特定的,而不一定适用于原先的hashMap适用的场景。

ThreadLocalMap是由一个个Entry键值对组成,key是ThreadLocal对象,value为线程变量的副本。每一个Thread都有一个ThreadLocalMap 类型的成员变量 threadLocals ,它存储本线程中所 有ThreadLocal对象及其对应的值。并且他是一个WeakReference 弱引用,当没有指向key的强引用后,该key就会被垃圾回收器回收。如果不是弱引用,那么因为这个 Map 的强引用导致这个线程的 ThreadLocalMap 对应的 ThreadLocal key 一直不能被回收。

2、减少哈希碰撞,如果你的程序需要多个 ThreadLocal,并且每个线程都使用了 这些 ThreadLocal。 Entry[] table 的大小一直是 2 的 n 次方,这样根据 Hash 值放入的时候,取余变成对于 2 的 n 次方 -1 取与运算。Hash 值计算是开放地址法,每新建一个 ThreadLocal 则将全局的 nextHashCode + 0x61c88647,这个魔法数保证了大部分情况下无论 Entry[] table 扩容到什么程度,都可以保证生成的 Hash 值 对于目前 table 大小的值 - 1 取与运算落入尽量不同的位置,减少哈希碰撞,增加效率。

那如果ThreadLocal发生内存泄漏,原因一定是弱引用吗?

ThreadLocal发生内存泄漏的关键在于,ThreadLocalMap和Thread有相同的生命周期,当外部没有强引用指向ThreadLocal时,在ThreadLocalMap里面的key就会被移除,而value还存在着强引用,只有当Thread退出线程后,value的强引用才会断,如果线程一直不结束的话,j这些key为null的Entry的value就会一直存在一条强引用链。

为什么TheadLocalMap设计成一个个entry对象,而不用hashMap?_第1张图片

 

ThreadLocal正确的使用方法

每次使用完ThreadLocal都调用它的remove()方法清除数据。

将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任 何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。

你可能感兴趣的:(多线程,java,开发语言)