ThreadLocal如何回收value,什么时候回收?(学习笔记)
https://www.cnblogs.com/1693977889zz/p/11111568.html
1)ThreadLocal如何回收value,什么时候回收?
从ThreadLocal中的内部类分析:
①
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
......
}
ThreadLocalMap是一个定制的哈希映射,仅适用于维护线程本地值。为了帮助处理非常大和长期使用的用法,哈希表条目使用weakreferences作为键。但是,由于不使用引用队列,因此只有当表开始耗尽空间时,才保证删除过时的条目。(源码注释)
②
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocalMap是使用ThreadLocal的弱引用作为Key的(注意:Value并非弱引用),Key只能是ThreadLocal对象,从而实现了变量访问在不同线程中的隔离。当一个ThreadLocal失去强引用,生命周期只能存活到下次gc前,此时ThreadLocalMap中就会出现key为null的Entry,当前线程无法结束,这些key为null的Entry的value就会一直存在一条强引用链,造成内存泄露。
解决方案:
建议将ThreadLocal变量定义成private static的,在调用ThreadLocal的get()、set()方法完成后,再调用remove()方法,手动删除不再需要的ThreadLocal。
2)ThreadLocal为什么会产生脏数据?
因为Thread Pool是一把双刃剑,好处略,坏处之一:
如果Thread是从Thread Pool中取出,它可能会被复用,此时就一定要保证这个Thread在上一次结束的时候,其关联的ThreadLocal被清空掉,否则就会串到下一次使用。
ThreadLocalMap的enrty的key为什么要设置成弱引用
ThreadLocalMap的Enrty代码实现:
将Entry的Key设置成弱引用,在配合线程池使用的情况下可能会有内存泄露的风险。之设计成弱引用的目的是为了更好地对ThreadLocal进行回收,当我们在代码中将ThreadLocal的强引用置为null后,这时候Entry中的ThreadLocal理应被回收了,但是如果Entry的key被设置成强引用则该ThreadLocal就不能被回收,这就是将其设置成弱引用的目的
https://blog.csdn.net/weixin_34162401/article/details/86024140