ThreadLocal刨根問底
一、ThreadLocal使用場景
資料庫連接connection對象使用,每個客戶都能使用自己的connection對象。不會出現客戶A操作關閉了客戶B的connection
案例://zhuanlan.zhihu.com/p/82737256
二、ThreadLocal中的remove()使用
1,記憶體泄露
2,在ThreadLocal和執行緒池聯合使用的時候,下個業務請求復用到這個執行緒的時候,也會用執行緒的ThreadLocal裡面的變數執行業務邏輯。
三、為什麼會出現記憶體泄露?
四、為什麼使用弱引用?
從表面上看,發生記憶體泄漏,是因為Key使用了弱引用類型。但其實是因為整個Entry的key為null後,沒有主動清除value導致。為什麼使用弱引用而不是強引用?
官方文檔的說法:
To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys.
為了處理非常大和生命周期非常長的執行緒,哈希表使用弱引用作為 key。
下面我們分兩種情況討論:
key 使用強引用:引用的ThreadLocal的對象被回收了,但是ThreadLocalMap還持有ThreadLocal的強引用,如果沒有手動刪除,ThreadLocal不會被回收,導致Entry記憶體泄漏。 key 使用弱引用:引用的ThreadLocal的對象被回收了,由於ThreadLocalMap持有ThreadLocal的弱引用,即使沒有手動刪除,ThreadLocal也會被回收。value在下一次ThreadLocalMap調用set,get,remove的時候會被清除。
比較兩種情況,我們可以發現:由於ThreadLocalMap的生命周期跟Thread一樣長,如果都沒有手動刪除對應key,都會導致記憶體泄漏,但是使用弱引用可以多一層保障:弱引用ThreadLocal不會記憶體泄漏,對應的value在下一次ThreadLocalMap調用set,get,remove的時候會被清除。
因此,ThreadLocal記憶體泄漏的根源是:由於ThreadLocalMap的生命周期跟Thread一樣長,如果沒有手動刪除對應key的value就會導致記憶體泄漏,而不是因為弱引用。