使用threadLocal提供的set方法将值保存,同时使用get来获取值,在每次使用完ThreadLocal使用remove方法对ThreadLocal进行清理用于防止内存泄露
在ThreadLocal中有一个自定义的hash map:ThreadLocalMap,其中使用的是数组来保存值
其中数组的类型是继承weakreference的Entry类型
源码中关于继承weakreference中有这样的说明
To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys. However, since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space.为了处理非常大的对象和长时间使用的对象,hash table实体使用弱引用来充当map的key,但是如果该值如果不被引用的使用,只有当内存满的时候,GC才会去回收这部分内存
这就是ThreadLocal会发生内存泄露的原因,由于弱引用的原因,会导致null的key对应一个非null的value,此时entry无法释放
从这里可以看出ThreadLocal使用的是循环数组的数据结构
这个方法的名字翻译过来是替换旧的实例,从中可以大概猜出该方法的用处
其中key是entry中的key,即当前的threadLocal对象;
value是其对应的值;
i是循环数组中key为null的entry在table中的索引的值;
从当前的位置向后查找key为null的entry,即无效的key,或者遇到空槽的位置,此时slotToExpunge = staleSlot
进行对数扫描的意思是:如果当前循环数组的长度是16,则每次n向左移一位,即16->8->4->2->1;共循环四次,将其中无效的值清除,到空槽的位置停止扫描
调用ThreadLocalMap中remove方法,其中执行如上文所提到的expungeStaleEntry方法
遇到空槽停止遍历
源码篇:ThreadLocal你真的理解透了吗?
ThreadLocal内存溢出代码演示