ThreadLocal可能引起的内存泄露
threadlocal里面使用了一個存在弱引用的map,當(dāng)釋放掉threadlocal的強(qiáng)引用以后,map里面的value卻沒有被回收.而這塊value永遠(yuǎn)不會被訪問到了. 所以存在著內(nèi)存泄露. 最好的做法是將調(diào)用threadlocal的remove方法.
在threadlocal的生命周期中,都存在這些引用. 看下圖: 實(shí)線代表強(qiáng)引用,虛線代表弱引用.
每個thread中都存在一個map, map的類型是ThreadLocal.ThreadLocalMap. Map中的key為一個threadlocal實(shí)例. 這個Map的確使用了弱引用,不過弱引用只是針對key. 每個key都弱引用指向threadlocal. 當(dāng)把threadlocal實(shí)例置為null以后,沒有任何強(qiáng)引用指向threadlocal實(shí)例,所以threadlocal將會被gc回收. 但是,我們的value卻不能回收,因?yàn)榇嬖谝粭l從current thread連接過來的強(qiáng)引用. 只有當(dāng)前thread結(jié)束以后, current thread就不會存在棧中,強(qiáng)引用斷開, Current Thread, Map, value將全部被GC回收.
所以得出一個結(jié)論就是只要這個線程對象被gc回收,就不會出現(xiàn)內(nèi)存泄露,但在threadLocal設(shè)為null和線程結(jié)束這段時間不會被回收的,就發(fā)生了我們認(rèn)為的內(nèi)存泄露。其實(shí)這是一個對概念理解的不一致,也沒什么好爭論的。最要命的是線程對象不被回收的情況,這就發(fā)生了真正意義上的內(nèi)存泄露。比如使用線程池的時候,線程結(jié)束是不會銷毀的,會再次使用的。就可能出現(xiàn)內(nèi)存泄露。
PS.Java為了最小化減少內(nèi)存泄露的可能性和影響,在ThreadLocal的get,set的時候都會清除線程Map里所有key為null的value。所以最怕的情況就是,threadLocal對象設(shè)null了,開始發(fā)生“內(nèi)存泄露”,然后使用線程池,這個線程結(jié)束,線程放回線程池中不銷毀,這個線程一直不被使用,或者分配使用了又不再調(diào)用get,set方法,那么這個期間就會發(fā)生真正的內(nèi)存泄露。
轉(zhuǎn)載于:https://www.cnblogs.com/panxuejun/p/8617088.html
總結(jié)
以上是生活随笔為你收集整理的ThreadLocal可能引起的内存泄露的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办信用卡需要什么条件?看你要办理什么卡!
- 下一篇: 《老友记》菲比谈剧集缺乏多样性:编剧没经