ThreadLocal什麼時候會出現OOM的情況?爲什麼?

ThreadLocal裏面使用了一個存在弱引用的map,當釋放掉threadlocal的強引用以後,map裏面的value卻沒有被回收.而這塊value永遠不會被訪問到了. 所以存在着內存泄露. 最好的做法是將調用threadlocal的remove方法.

在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爲了最小化減少內存泄露的可能性和影響,在ThreadLocal的get,set的時候都會清除線程Map裏所有key爲null的value。所以最怕的情況就是,threadLocal對象設null了,開始發生“內存泄露”,然後使用線程池,這個線程結束,線程放回線程池中不銷燬,這個線程一直不被使用,或者分配使用了又不再調用get,set方法,那麼這個期間就會發生真正的內存泄露。

轉載地址:https://www.cnblogs.com/onlywujun/p/3524675.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章