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時會被回收掉,前提條件是弱引用的對象不存在其它的強引用和軟引用。