狂奔 lion

          自強不息

          關(guān)于ThreadLocal的內(nèi)存泄露

          ThreadLocal是一種confinement,confinement和local及immutable都是線程安全的(如果JVM可信的話)。因為對每個線程和value之間存在hash表,而線程數(shù)量未知,從表象來看ThreadLocal會存在內(nèi)存泄露,讀了代碼,發(fā)現(xiàn)實際上也可能會內(nèi)存泄露。

          事實上每個Thread實例都具備一個ThreadLocal的map,以ThreadLocal Instance為key,以綁定的Object為Value。而這個map不是普通的map,它是在ThreadLocal中定義的,它和普通map的最大區(qū)別就是它的Entry是針對ThreadLocal弱引用的,即當(dāng)外部ThreadLocal引用為空時,map就可以把ThreadLocal交給GC回收,從而得到一個null的key。

          這個threadlocal內(nèi)部的map在Thread實例內(nèi)部維護(hù)了ThreadLocal Instance和bind value之間的關(guān)系,這個map有threshold,當(dāng)超過threshold時,map會首先檢查內(nèi)部的ThreadLocal(前文說過,map是弱引用可以釋放)是否為null,如果存在null,那么釋放引用給gc,這樣保留了位置給新的線程。如果不存在slate threadlocal,那么double threshold。除此之外,還有兩個機會釋放掉已經(jīng)廢棄的threadlocal占用的內(nèi)存,一是當(dāng)hash算法得到的table index剛好是一個null key的threadlocal時,直接用新的threadlocal替換掉已經(jīng)廢棄的。另外每次在map中新建一個entry時(即沒有和用過的或未清理的entry命中時),會調(diào)用cleanSomeSlots來遍歷清理空間。此外,當(dāng)Thread本身銷毀時,這個map也一定被銷毀了(map在Thread之內(nèi)),這樣內(nèi)部所有綁定到該線程的ThreadLocal的Object Value因為沒有引用繼續(xù)保持,所以被銷毀。

          從上可以看出Java已經(jīng)充分考慮了時間和空間的權(quán)衡,但是因為置為null的threadlocal對應(yīng)的Object Value無法及時回收。map只有到達(dá)threshold時或添加entry時才做檢查,不似gc是定時檢查,不過我們可以手工輪詢檢查,顯式調(diào)用map的remove方法,及時的清理廢棄的threadlocal內(nèi)存。需要說明的是,只要不往不用的threadlocal中放入大量數(shù)據(jù),問題不大,畢竟還有回收的機制。

          綜上,廢棄threadlocal占用的內(nèi)存會在3中情況下清理:
          1 thread結(jié)束,那么與之相關(guān)的threadlocal value會被清理
          2 GC后,thread.threadlocals(map) threshold超過最大值時,會清理
          3 GC后,thread.threadlocals(map) 添加新的Entry時,hash算法沒有命中既有Entry時,會清理

          那么何時會“內(nèi)存泄露”?當(dāng)Thread長時間不結(jié)束,存在大量廢棄的ThreadLocal,而又不再添加新的ThreadLocal(或新添加的ThreadLocal恰好和一個廢棄ThreadLocal在map中命中)時。

           @2008 楊一. 版權(quán)所有. 保留所有權(quán)利

          posted on 2010-07-02 18:27 楊一 閱讀(2290) 評論(2)  編輯  收藏 所屬分類: Java SEOther Tech

          評論

          # re: 關(guān)于ThreadLocal的內(nèi)存泄露[未登錄] 2010-07-03 09:32 m

          他的目的就是在thread的生命周期內(nèi)維持變量。thread沒結(jié)束肯定不會掉呀~  回復(fù)  更多評論   

          # re: 關(guān)于ThreadLocal的內(nèi)存泄露[未登錄] 2010-07-03 10:44 楊一

          @m
          那如果thread isdeamon呢,thread不同于普通的對象  回復(fù)  更多評論   

          <2010年7月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          公告

          本人在blogjava上發(fā)表的文章及隨筆除特別聲明外均為原創(chuàng)或翻譯,作品受知識產(chǎn)權(quán)法保護(hù)并被授權(quán)遵從 知識分享協(xié)議:署名-非商業(yè)性使用-相同方式共享 歡迎轉(zhuǎn)載,請在轉(zhuǎn)載時注明作者姓名(楊一)及出處(www.aygfsteel.com/yangyi)
          /////////////////////////////////////////
          我的訪問者

          常用鏈接

          留言簿(5)

          隨筆分類(55)

          隨筆檔案(55)

          相冊

          Java

          其他技術(shù)

          生活

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          自強不息


          用心 - 珍惜時間,勇于創(chuàng)造
          主站蜘蛛池模板: 贺兰县| 广饶县| 海门市| 富民县| 大化| 兴业县| 驻马店市| 宿迁市| 广南县| 佛冈县| 金山区| 盐亭县| 巴彦县| 广州市| 龙胜| 保德县| 襄樊市| 岳池县| 三原县| 奎屯市| 廊坊市| 镇赉县| 驻马店市| 固始县| 汨罗市| 炎陵县| 兴安县| 屏南县| 南陵县| 闻喜县| 密云县| 弥勒县| 咸丰县| 公主岭市| 丰台区| 祁东县| 甘谷县| 会昌县| 汉中市| 巴彦县| 翁源县|