Luogu6139 【模板】廣義字尾自動機(廣義 SAM)
ThreadLocal
map 和thread 關聯 map裡面的鍵是threadLocal 物件, value 是值
Thread ThreadLocalMap ThreaLocal 關係
- Thread內含ThreadLocalMap, 放入(this, value)
![](_assets/
用處
Spring的事務管理,用ThreadLocal儲存Connection,從而各個DAO可以獲取同一Connection,可以進行事務回滾,提交等操作。
- 先從對應執行緒上獲取對應的ThreadLocalMap 從ThreadLocalMap 中根據ThreadLocal 鍵值 設定值
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } // 1個執行緒對應一個 ThreadLocalMap void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); } // ThreadLocalMap ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }
強引用、軟引用、弱引用和虛引用
tab[i] = new Entry(key, value); 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. */ static class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
WeakReference對應用的物件userInfoLocal是弱引用,不會影響到userInfoLocal的GC行為。如果是強引用的話,線上程執行過程中,我們不再使用userInfoLocal了,將userInfoLocal置為null,但userInfoLocal線上程的ThreadLocalMap裡還有引用,導致其無法被GC回收(當然,可以等到執行緒執行結束後,整個Map都會被回收,但很多執行緒要執行很久,如果等到執行緒結束,便會一直佔著記憶體空間)。而Entry宣告為WeakReference,userInfoLocal置為null後,執行緒的threadLocalMap就不算強引用了,userInfoLocal就可以被GC回收了。map的後續操作中,也會逐漸把對應的"stale entry"清理出去,避免記憶體洩漏。
實際上只要ThreadLocal被定義成static的,那個WeakReference就是沒有用的。因為static欄位就是強引用,並且只要class load之後就永遠可達
那個WeakReference可能有用的時候是ThreadLocal不被定義為static的,它被作為引數在方法之間以及各執行緒之間傳遞。等到所有執行緒都不再能訪問到它了,GC會把它回收。但是此時map裡的那個entry還在,它包裹的物件是null了,那個value值也還在。它會在下一次expungeStaleEntry時被從map中清理掉。
ThreadLocalMap內部Entry中key使用的是對ThreadLocal物件的弱引用,這為避免記憶體洩露是一個進步,因為如果是強引用,那麼即使其他地方沒有對ThreadLocal物件的引用,ThreadLocalMap中的ThreadLocal物件還是不會被回收,而如果是弱引用則這時候ThreadLocal引用是會被回收掉的,雖然對於的value還是不能被回收,這時候ThreadLocalMap裡面就會存在key為null但是value不為null的entry項,雖然ThreadLocalMap提供了set,get,remove方法在一些時機下會對這些Entry項進行清理,但是這是不及時的,也不是每次都會執行的,所以一些情況下還是會發生記憶體洩露,所以在使用完畢後即使呼叫remove方法才是解決記憶體洩露的王道
為什麼使用完要清除:
使用的是執行緒池,建立的ThradeLocal 是作為Key 放線上程繫結的ThradLocalMap中的,不清除越來越對炸了