Thread对象有一个变量名为threadLocals的ThreadLocalMap对象,里面定义了一个Entry数组,Entry对象弱引用了ThreadLocal。
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
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();
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
Entry弱引用了ThreadLocal,因此Entry是否存活,不会影响ThreadLocal的生命周期,ThreadLocal在没有其它对象引用后被回收,但是它对应的Entry对象中的value实际还在被Entry引用,如果不清掉Entry,value就会一直强引用,无法释放,那么就可能会内存溢出。(用完要remove()或者下次set()时会检查)
弱引用在下次GC时会被回收掉,前提条件是弱引用的对象不存在其它的强引用和软引用。
实时内容请关注微信公众号,公众号与博客同时更新:程序员星星