1)ThreadLocal如何回收value,何時回收?
從ThreadLocal中的內部類分析:
①this
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做爲鍵。可是,因爲不使用引用隊列,所以只有當表開始耗盡空間時,才保證刪除過期的條目。(源碼註釋)
② spa
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被清空掉,不然就會串到下一次使用。線程