ThreadLocal

ThreadLocal是什么

ThreadLocal是一個(gè)關(guān)于創(chuàng)建線程局部變量的類。

通常情況下锌奴,我們創(chuàng)建的變量是可以被任何一個(gè)線程訪問并修改的兽狭。而使用ThreadLocal創(chuàng)建的變量只能被當(dāng)前線程訪問憾股,其他線程則無法訪問和修改鹿蜀。

本文需要解決一下幾個(gè)問題

  • 每個(gè)線程的變量副本是存儲(chǔ)在哪里的箕慧?

  • 變量副本是怎么從共享的那個(gè)變量賦值出來的?源碼中的threadlocal的初始值是什么時(shí)機(jī)設(shè)置的茴恰?

  • ThreadLocal是如何實(shí)現(xiàn)了多個(gè)線程之間每個(gè)線程一個(gè)變量副本的颠焦?它是如何實(shí)現(xiàn)共享變量的。

ThreadLocal機(jī)制主要由Entry往枣、ThreadLocalMap伐庭、Thread、ThreadLocal這四個(gè)類相互協(xié)作實(shí)現(xiàn)的分冈。


我們來看set()方法

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

這個(gè)方法用當(dāng)前線程t圾另,去獲取實(shí)體map,并set雕沉,如果沒有則Creat


我們?cè)賮砜?strong>get()方法

    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();
    }

同set方法差不多

我們來看看**ThreadLocalMap **

//初始化大小
private static final int INITIAL_CAPACITY = 16;
//容器為數(shù)組
private Entry[] table;

Entry

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

Entry的定義很簡(jiǎn)單集乔,它擴(kuò)展自ThreadLocal類型的WeakReference類,是一個(gè)key-value對(duì)類坡椒。key是ThreadLocal對(duì)象的弱引用扰路,value是線程的內(nèi)部變量。

Entry使用弱引用作為key目的是倔叼,希望在外部不再需要訪問ThreadLocal對(duì)象時(shí)可以讓GC盡快地回收對(duì)象汗唱,而不必等到線程結(jié)束后。

當(dāng)GC回收ThreadLocal對(duì)象后丈攒,再通過Entry.get()獲取ThreadLocal對(duì)象時(shí)返回null哩罪,這使得內(nèi)部能夠感知什么時(shí)候不需要再持有對(duì)value的引用,從而釋放Entry對(duì)象的引用巡验,進(jìn)而釋放value的引用识椰,這時(shí)如果value在外部沒有任何引用的話(通常你不應(yīng)該在外部持有對(duì)value的引用),隨后被GC回收深碱。這種感知和釋放的行為發(fā)生在ThreadLocal的get腹鹉、set、remove操作時(shí)敷硅。


通常在Java的世界里功咒,我們不需要關(guān)系對(duì)象的釋放,大部分情況下GC會(huì)自動(dòng)幫我們回收绞蹦。

但是如果使用ThreadLocal不當(dāng)力奋,是有可能導(dǎo)致內(nèi)存泄漏的。

ThreadLocal釋放內(nèi)部變量通常在以下時(shí)機(jī):

線程結(jié)束后
顯式調(diào)用remove
在調(diào)用get幽七、set時(shí)景殷,如果探測(cè)到ThreadLocal對(duì)象的弱引用對(duì)象get返回null順便釋放。
所以,如果線程存活的生命周期很長(zhǎng)猿挚,特別是和進(jìn)程一樣長(zhǎng)的話咐旧,就要特別注意防止ThreadLocal引入內(nèi)存泄漏的風(fēng)險(xiǎn),在不需要再使用某個(gè)線程內(nèi)部變量時(shí)記得顯式調(diào)用remove清理掉绩蜻。

參考
理解ThreadLocal
理解Java中的ThreadLocal

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铣墨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子办绝,更是在濱河造成了極大的恐慌伊约,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孕蝉,死亡現(xiàn)場(chǎng)離奇詭異屡律,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)降淮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門疹尾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骤肛,你說我怎么就攤上這事纳本。” “怎么了腋颠?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵繁成,是天一觀的道長(zhǎng)蜀备。 經(jīng)常有香客問我衷笋,道長(zhǎng),這世上最難降的妖魔是什么闪湾? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任絮蒿,我火速辦了婚禮尊搬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘土涝。我一直安慰自己佛寿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布但壮。 她就那樣靜靜地躺著冀泻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜡饵。 梳的紋絲不亂的頭發(fā)上弹渔,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音溯祸,去河邊找鬼肢专。 笑死舞肆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的博杖。 我是一名探鬼主播椿胯,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼欧募!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仆抵,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤跟继,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后镣丑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舔糖,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年莺匠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了金吗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趣竣,死狀恐怖摇庙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情遥缕,我是刑警寧澤卫袒,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站单匣,受9級(jí)特大地震影響夕凝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜户秤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一码秉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸡号,春花似錦转砖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挑围,卻和暖如春礁竞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杉辙。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工模捂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓狂男,卻偏偏與公主長(zhǎng)得像综看,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岖食,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容