1. 程式人生 > 其它 >ThreadLocal可能引起的記憶體洩露

ThreadLocal可能引起的記憶體洩露

threadlocal裡面使用了一個存在弱引用的map,當釋放掉threadlocal的強引用以後,map裡面的value卻沒有被回收.而這塊value永遠不會被訪問到了. 所以存在著記憶體洩露. 最好的做法是將呼叫threadlocalremove方法.

threadlocal的生命週期中,都存在這些引用. 看下圖: 實線代表強引用,虛線代表弱引用.

每個thread中都存在一個map, map的型別是ThreadLocal.ThreadLocalMap. Map中的key為一個threadlocal例項. 這個Map的確使用了弱引用,不過弱引用只是針對key. 每個key都弱引用指向

threadlocal. 當把threadlocal例項置為null以後,沒有任何強引用指向threadlocal例項,所以threadlocal將會被gc回收. 但是,我們的value卻不能回收,因為存在一條從current thread連線過來的強引用. 只有當前thread結束以後, current thread就不會存在棧中,強引用斷開, Current Thread, Map, value將全部被GC回收.

所以得出一個結論就是隻要這個執行緒物件被gc回收,就不會出現記憶體洩露,但在threadLocal設為null和執行緒結束這段時間不會被回收的,就發生了我們認為的記憶體洩露。其實這是一個對概念理解的不一致,也沒什麼好爭論的。最要命的是執行緒物件不被回收的情況,這就發生了真正意義上的記憶體洩露

。比如使用執行緒池的時候,執行緒結束是不會銷燬的,會再次使用的。就可能出現記憶體洩露。  

PS.Java為了最小化減少記憶體洩露的可能性和影響,在ThreadLocalget,set的時候都會清除執行緒Map裡所有keynullvalue。所以最怕的情況就是,threadLocal物件設null了,開始發生“記憶體洩露”,然後使用執行緒池,這個執行緒結束,執行緒放回執行緒池中不銷燬,這個執行緒一直不被使用,或者分配使用了又不再呼叫get,set方法,那麼這個期間就會發生真正的記憶體洩露