ThreadLocal可能引起的記憶體洩露
阿新 • • 發佈:2022-05-31
threadlocal裡面使用了一個存在弱引用的map,當釋放掉threadlocal的強引用以後,map裡面的value卻沒有被回收.而這塊value永遠不會被訪問到了. 所以存在著記憶體洩露. 最好的做法是將呼叫threadlocal的remove方法.
在threadlocal的生命週期中,都存在這些引用. 看下圖: 實線代表強引用,虛線代表弱引用.
每個thread中都存在一個map, map的型別是ThreadLocal.ThreadLocalMap. Map中的key為一個threadlocal例項. 這個Map的確使用了弱引用,不過弱引用只是針對key. 每個key都弱引用指向
所以得出一個結論就是隻要這個執行緒物件被gc回收,就不會出現記憶體洩露,但在threadLocal設為null和執行緒結束這段時間不會被回收的,就發生了我們認為的記憶體洩露。其實這是一個對概念理解的不一致,也沒什麼好爭論的。最要命的是執行緒物件不被回收的情況,這就發生了真正意義上的記憶體洩露 。比如使用執行緒池的時候,執行緒結束是不會銷燬的,會再次使用的。就可能出現記憶體洩露。
PS.Java為了最小化減少記憶體洩露的可能性和影響,在ThreadLocal的get,set的時候都會清除執行緒Map裡所有key為null的value。所以最怕的情況就是,threadLocal物件設null了,開始發生“記憶體洩露”,然後使用執行緒池,這個執行緒結束,執行緒放回執行緒池中不銷燬,這個執行緒一直不被使用,或者分配使用了又不再呼叫get,set方法,那麼這個期間就會發生真正的記憶體洩露。