Thread有一個ThreadLocal.ThreadLocalMap類型的threadLocals成員變量,他是一個map,底層是一個ThreadLocalMap.Entry的數組,每一個ThreadLocal變量都有一個threadLocalHashCode,根據這個hashcode可計算出當前ThreadLocal在數組的index值。
ThreadLocalMap.Entry是一個弱引用類型WeakReference<ThreadLocal<?>>,Entry的value就是咱們須要存儲的對象,而key則是一個弱引用的referent,當ThreadLocal沒有任何強引用時,GC後即便還有弱應用存在也會被回收,這時Entry的key爲null。因此即便線程一直活着,只要ThreadLocal不存在任何強引用,就會被回收器回收,避免內存泄漏。數組
那麼問題來了,即便Entry的key爲弱引用會被回收,但value一直以key爲null的Entry保存在map中,這是強引用,永遠不會被回收。ThreadLocalMap的解決方法是在每次get、set、remove時都會將key爲null的entry清除掉,這樣就會被垃圾回收器清理了。spa
爲何不將entry的value也設置爲弱引用呢,這是由於若是value是弱引用,執行GC後,若value被清除,那咱們永遠也拿不到ThreadLocal保存的數據了。線程
一般實踐中,咱們常把ThreadLocal作爲單例使用,由於咱們要保證key爲ThreadLocal的值全局都能訪問到。當不是單例使用狀況下,咱們要記得在不實用ThreadLocal時調用一下ThreadLocal.remove()方法,刪除key。help gc.code