1)ThreadLocal如何回收value,什麼時候回收?從ThreadLocal中的內部類分析:① ThreadLocalMap是一個定製的哈希映射,僅適用於維護線程本地值。為了幫助處理非常大和長期使用的用法,哈希表條目使用weakreferences作為鍵。但是,由於不使用引用隊列,因此只有當 ...
1)ThreadLocal如何回收value,什麼時候回收?
從ThreadLocal中的內部類分析:
①
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. */ ...... }
ThreadLocalMap是一個定製的哈希映射,僅適用於維護線程本地值。為了幫助處理非常大和長期使用的用法,哈希表條目使用weakreferences作為鍵。但是,由於不使用引用隊列,因此只有當表開始耗盡空間時,才保證刪除過時的條目。(源碼註釋)
②
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
ThreadLocalMap是使用ThreadLocal的弱引用作為Key的(註意:Value並非弱引用),Key只能是ThreadLocal對象,從而實現了變數訪問在不同線程中的隔離。當一個ThreadLocal失去強引用,生命周期只能存活到下次gc前,此時ThreadLocalMap中就會出現key為null的Entry,當前線程無法結束,這些key為null的Entry的value就會一直存在一條強引用鏈,造成記憶體泄露。
解決方案:
建議將ThreadLocal變數定義成private static的,在調用ThreadLocal的get()、set()方法完成後,再調用remove()方法,手動刪除不再需要的ThreadLocal。
2)ThreadLocal為什麼會產生臟數據?
因為Thread Pool是一把雙刃劍,好處略,壞處之一:
如果Thread是從Thread Pool中取出,它可能會被覆用,此時就一定要保證這個Thread在上一次結束的時候,其關聯的ThreadLocal被清空掉,否則就會串到下一次使用。