ThreadLocal學習

ThreadLocal是什么

ThreadLocal是一個本地線程副本變量工具類枫吧。主要用于將私有線程和該線程存放的副本對象做一個映射雳灾,各個線程之間的變量互不干擾,在高并發(fā)場景下季二,可以實現(xiàn)無狀態(tài)的調用伞剑,特別適用于各個線程依賴不通的變量值完成操作的場景

ThreadLoacl數(shù)據(jù)結構

image.png

通過上圖可以看出

  • 每一個線程都維護這一個ThreadLocalMap的數(shù)組,這個就是實現(xiàn)線程之間互不影響的原因胆数,因為每個線程自己維護了一個Entry肌蜻。
  • ThreadLocal只是用來管理每個線程中Entry的一個工具,因為真正的ThreadLocalMap是定義在每一個線程中,可以通過ThreadLocal的get,set方法明白這一切
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
##通過Thread.currentThread獲取到當前線程
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}
#設置時候必尼,ThreadLocalMap的key值就是threadLocal,所以后面可以通過ThreadLocal獲取到這個entry的value值
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
 }

  • 為啥是一個Entry數(shù)組宋欺?因為可能你定義了多個ThreadLocal變量,每個ThreadLocal指向一個Entry,這樣不同的ThreadLocal可以操作不同的數(shù)據(jù)
public class ThreadLocalTest {
    static ThreadLocal LOCAL = new ThreadLocal();
    static ThreadLocal LOCAL2 = new ThreadLocal();
}
  • ThreadLocalMap如何解決Hash沖突胰伍?ThreadLocalMap是定義再ThreadLocal類中的一個數(shù)據(jù)結構齿诞,他采用的是線性探測的方式而非像HashMap采用鏈表的模式。所謂線性探測骂租,就是根據(jù)初始key的hashcode值確定元素在table數(shù)組中的位置祷杈,如果發(fā)現(xiàn)這個位置上已經(jīng)有其他key值的元素被占用,則利用固定的算法尋找一定步長的下個位置渗饮,依次判斷但汞,直至找到能夠存放的位置。基于這特點互站,建議最好Entry[]的數(shù)量不要太多私蕾,所以這里引出的良好建議是:每個線程只存一個變量,這樣的話所有的線程存放到map中的Key都是相同的ThreadLocal胡桃,如果一個線程要保存多個變量踩叭,就需要創(chuàng)建多個ThreadLocal,多個ThreadLocal放入Map中時會極大的增加Hash沖突的可能
  • 從結構圖可以看出翠胰,用ThreadLocal時候set進去的對象必須是每個線程單獨new出來的容贝,例如先new了一個對象X,然后后面多線程里面set(X),這樣其實每一個線程中Entry的Value指向的是同一個對象X之景,這樣會有問題

ThreadLocal內(nèi)存泄露

image.png

為什么會內(nèi)存泄漏?

ThreadLocal在ThreadLocalMap中是以一個弱引用身份被Entry中的Key引用的斤富,因此如果ThreadLocal沒有外部強引用來引用它,那么ThreadLocal會在下次JVM垃圾收集時被回收锻狗。這個時候就會出現(xiàn)Entry中Key已經(jīng)被回收满力,出現(xiàn)一個null Key的情況焕参,外部讀取ThreadLocalMap中的元素是無法通過null Key來找到Value的。因此如果當前線程的生命周期很長油额,一直存在龟糕,那么其內(nèi)部的ThreadLocalMap對象也一直生存下來,這些null key就存在一條強引用鏈的關系一直存在:Thread --> ThreadLocalMap-->Entry-->Value悔耘,這條強引用鏈會導致Entry不會回收,Value也不會回收我擂,但Entry中的Key卻已經(jīng)被回收的情況衬以,造成內(nèi)存泄漏
從上可以看出導致內(nèi)存泄露的幾個原因:

  • 使用static的ThreadLocal,延長了ThreadLocal的生命周期校摩,可能導致的內(nèi)存泄漏
  • 分配使用了ThreadLocal又不再調用get()看峻、set()、remove()方法衙吩,那么就會導致內(nèi)存泄漏
  • 由于ThreadLocalMap的生命周期跟Thread一樣長互妓,如果沒有手動刪除對應key的value就會導致內(nèi)存泄漏,而不是因為弱引用

解決方法

每次使用完ThreadLocal坤塞,都調用它的remove()方法冯勉,清除數(shù)據(jù)。如果一個線程執(zhí)行時間過長摹芙,代碼上可以將threadlocal用完后馬上remove掉灼狰,防止后面代碼執(zhí)行過程導致value值一直得不到釋放

參考

http://www.reibang.com/p/98b68c97df9b

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市浮禾,隨后出現(xiàn)的幾起案子交胚,更是在濱河造成了極大的恐慌窒舟,老刑警劉巖色难,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虱歪,居然都是意外死亡匆帚,警方通過查閱死者的電腦和手機熬词,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吸重,“玉大人荡澎,你說我怎么就攤上這事∥钋拢” “怎么了摩幔?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鞭铆。 經(jīng)常有香客問我或衡,道長焦影,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任封断,我火速辦了婚禮斯辰,結果婚禮上,老公的妹妹穿的比我還像新娘坡疼。我一直安慰自己彬呻,他們只是感情好,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布柄瑰。 她就那樣靜靜地躺著闸氮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪教沾。 梳的紋絲不亂的頭發(fā)上蒲跨,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音授翻,去河邊找鬼或悲。 笑死,一個胖子當著我的面吹牛堪唐,可吹牛的內(nèi)容都是我干的巡语。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淮菠,長吁一口氣:“原來是場噩夢啊……” “哼捌臊!你這毒婦竟也來了?” 一聲冷哼從身側響起兜材,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤理澎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后曙寡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糠爬,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年举庶,在試婚紗的時候發(fā)現(xiàn)自己被綠了执隧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡户侥,死狀恐怖镀琉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蕊唐,我是刑警寧澤屋摔,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站替梨,受9級特大地震影響钓试,放射性物質發(fā)生泄漏装黑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一弓熏、第九天 我趴在偏房一處隱蔽的房頂上張望恋谭。 院中可真熱鬧,春花似錦挽鞠、人聲如沸疚颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽材义。三九已至,卻和暖如春狮杨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背到忽。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工橄教, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喘漏。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓护蝶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翩迈。 傳聞我的和親對象是個殘疾皇子持灰,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354