如上图所示html
每一个Thread 都有一个map,里面存着Entry<Key,value>,而key
是实现了WeakReference
的ThreadLocal
,若是不是WeakReference
,那么可能Entry里面的key和value在线程结束才会进行GC,可是因为是WeakReference
,所以当Key被设置为null
时,key就会被 gc 回收.spa
可是因为value
还在currentThread
->Map
->Entry
->value
中,所以致使了内存泄漏线程
hreadLocalMap类的设计自己已经有了这一问题的解决方案,那就是在每次get()
/set()
/remove()
ThreadLocalMap中的值的时候,会自动清理key为null的value。如此一来,value也能被回收了。设计
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) { Entry[] tab = table; int len = tab.length; while (e != null) { ThreadLocal<?> k = e.get(); if (k == key) return e; if (k == null) expungeStaleEntry(i); else i = nextIndex(i, len); e = tab[i]; } return null; }
中的code
if (k == null) expungeStaleEntry(i);
expungeStaleEntry保证了key为null的状况下value也置为nullhtm
private int expungeStaleEntry(int staleSlot) { Entry[] tab = table; int len = tab.length; // expunge entry at staleSlot tab[staleSlot].value = null; tab[staleSlot] = null; size--; // Rehash until we encounter null Entry e; int i; for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { ThreadLocal<?> k = e.get(); if (k == null) { e.value = null; tab[i] = null; size--; } else { int h = k.threadLocalHashCode & (len - 1); if (h != i) { tab[i] = null; // Unlike Knuth 6.4 Algorithm R, we must scan until // null because multiple entries could have been stale. while (tab[h] != null) h = nextIndex(h, len); tab[h] = e; } } } return i; }
原文出处:https://www.cnblogs.com/Draymonder/p/10433516.htmlblog