先看下ThreadLocalMap的设计
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
ThreadLocalMap 是由Entry 构成,而Entry 继承自 WeakReference
Entry 是 弱引用
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
为什么要设计成弱引用?
当GC的时候ThreadLocal就会被清除,如果是强引用则它会一直占用内存直到ThreadLocalMap被释放,如果ThreadLocalMap一直不被释放哪就出现内存泄漏了。
设计Entry成弱引用就不会内存泄漏?
要知道ThreadLocalMap 是以ThreadLocal 作为Key的map。ThreadLocal被GC回收后key就变成null,一个map如果key == null ,那它的value 你永远都访问不到。同样会出现内存泄漏。
如何避免Value的内存泄漏?
养成良好的编程习惯,不用的时候ThreadLocal.remove()