手撕面試題 ThreadLocal题翻!

說明

面試官:講講你對ThreadLocal的一些理解。

那么我們該怎么回答呢腰鬼?嵌赠?靴拱??你也可以思考下猾普,下面看看零度的思考袜炕;

  • ThreadLocal用在什么地方?

  • ThreadLocal一些細(xì)節(jié)初家!

  • ThreadLocal的最佳實踐偎窘!

  • 思考

ThreadLocal用在什么地方?

討論ThreadLocal用在什么地方前溜在,我們先明確下陌知,如果僅僅就一個線程,那么都不用談ThreadLocal的掖肋,ThreadLocal是用在多線程的場景的F推稀!志笼!

ThreadLocal歸納下來就2類用途:

  • 保存線程上下文信息沿盅,在任意需要的地方可以獲取H依!!窖铡!
  • 線程安全的费彼,避免某些情況需要考慮線程安全必須同步帶來的性能損失9坎:缗ァ!

保存線程上下文信息,在任意需要的地方可以獲鹊憾肌>室摺!!

由于ThreadLocal的特性拔创,同一線程在某地方進(jìn)行設(shè)置剩燥,在隨后的任意地方都可以獲取到灭红。從而可以用來保存線程上下文信息比伏。

常用的比如每個請求怎么把一串后續(xù)關(guān)聯(lián)起來,就可以用ThreadLocal進(jìn)行set悠菜,在后續(xù)的任意需要記錄日志的方法里面進(jìn)行g(shù)et獲取到請求id悔醋,從而把整個請求串起來。

還有比如Spring的事務(wù)管理账阻,用ThreadLocal存儲Connection淘太,從而各個DAO可以獲取同一Connection撇贺,可以進(jìn)行事務(wù)回滾松嘶,提交等操作。

備注: ThreadLocal的這種用處蕴轨,很多時候是用在一些優(yōu)秀的框架里面的骇吭,一般我們很少接觸棘脐,反而下面的場景我們接觸的更多一些蛀缝!

線程安全的屈梁,避免某些情況需要考慮線程安全必須同步帶來的性能損失!9共浮曙强!

ThreadLocal為解決多線程程序的并發(fā)問題提供了一種新的思路。但是ThreadLocal也有局限性臀防,我們來看看阿里規(guī)范:

image

每個線程往ThreadLocal中讀寫數(shù)據(jù)是線程隔離,互相之間不會影響的,所以ThreadLocal無法解決共享對象的更新問題嫌蚤!

由于不需要共享信息脱吱,自然就不存在競爭問題了,從而保證了某些情況下線程的安全宦搬,以及避免了某些情況需要考慮線程安全必須同步帶來的性能損失!c咀恪!

這類場景阿里規(guī)范里面也提到了:

image

ThreadLocal一些細(xì)節(jié)!

ThreaLocal使用示例代碼:

public class ThreadLocalTest {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {

        new Thread(() -> {
            try {
                for (int i = 0; i < 100; i++) {
                    threadLocal.set(i);
                    System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                threadLocal.remove();
            }
        }, "threadLocal1").start();


        new Thread(() -> {
            try {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                threadLocal.remove();
            }
        }, "threadLocal2").start();
    }
}

代碼截圖:

image

代碼運行結(jié)果:

image

從運行的結(jié)果我們可以看到threadLocal1進(jìn)行set值對threadLocal2并沒有任何影響!

Thread畦徘、ThreadLocalMap关筒、ThreadLocal總覽圖

image
image

Thread類有屬性變量threadLocals (類型是ThreadLocal.ThreadLocalMap)袍榆,也就是說每個線程有一個自己的ThreadLocalMap ,所以每個線程往這個ThreadLocal中讀寫隔離的才写,并且是互相不會影響的锭硼。

一個ThreadLocal只能存儲一個Object對象轰异,如果需要存儲多個Object對象那么就需要多個ThreadLocal!Q栏巍雹姊!

如圖:

image

看到上面的幾個圖瘾境,大概思路應(yīng)該都清晰了,我們Entry的key指向ThreadLocal用虛線表示弱引用 懂更,下面我們來看看ThreadLocalMap:

image

java對象的引用包括 : 強(qiáng)引用慷暂,軟引用,弱引用,虛引用 。

因為這里涉及到弱引用座慰,簡單說明下:

弱引用也是用來描述非必需對象的,當(dāng)JVM進(jìn)行垃圾回收時翠拣,無論內(nèi)存是否充足版仔,該對象僅僅被弱引用關(guān)聯(lián),那么就會被回收误墓。

當(dāng)僅僅只有ThreadLocalMap中的Entry的key指向ThreadLocal的時候蛮粮,ThreadLocal會進(jìn)行回收的!S派铡蝉揍!

ThreadLocal被垃圾回收后,在ThreadLocalMap里對應(yīng)的Entry的鍵值會變成null畦娄,但是Entry是強(qiáng)引用又沾,那么Entry里面存儲的Object弊仪,并沒有辦法進(jìn)行回收,所以ThreadLocalMap 做了一些額外的回收工作杖刷。

image

雖然做了但是也會存在內(nèi)存泄漏風(fēng)險(我沒有遇到過励饵,網(wǎng)上很多類似場景,所以會提到后面的ThreadLocal最佳實踐;肌R厶!

ThreadLocal的最佳實踐表窘!

ThreadLocal被垃圾回收后典予,在ThreadLocalMap里對應(yīng)的Entry的鍵值會變成null,但是Entry是強(qiáng)引用乐严,那么Entry里面存儲的Object瘤袖,并沒有辦法進(jìn)行回收,所以ThreadLocalMap 做了一些額外的回收工作昂验。

image

備注: 很多時候捂敌,我們都是用在線程池的場景,程序不停止既琴,線程基本不會銷毀U纪瘛!甫恩!

由于線程的生命周期很長逆济,如果我們往ThreadLocal里面set了很大很大的Object對象,雖然set填物、get等等方法在特定的條件會調(diào)用進(jìn)行額外的清理纹腌,但是ThreadLocal被垃圾回收后,在ThreadLocalMap里對應(yīng)的Entry的鍵值會變成null滞磺,但是后續(xù)在也沒有操作set升薯、get等方法了。

所以最佳實踐击困,應(yīng)該在我們不使用的時候涎劈,主動調(diào)用remove方法進(jìn)行清理。

image

這里把ThreadLocal定義為static還有一個好處就是阅茶,由于ThreadLocal有強(qiáng)引用在蛛枚,那么在ThreadLocalMap里對應(yīng)的Entry的鍵會永遠(yuǎn)存在,那么執(zhí)行remove的時候就可以正確進(jìn)行定位到并且刪除A嘲А1钠帧!

最佳實踐做法應(yīng)該為:

try {
    // 其它業(yè)務(wù)邏輯
} finally {
    threadLocal對象.remove();
}
image

思考

如果面試的時候撞蜂,可以把上面的內(nèi)容都可以講到盲镶,個人覺得就非常好了侥袜,回答的就挺完美了。但是如果你可以進(jìn)行下面的回答溉贿,那么就更完美了枫吧。

對于ThreadLocal,我在看Netty源碼的時候宇色,還了解過FastThreadLocal九杂,xxxxx一些列內(nèi)容,那就是一個升級了宣蠕。

image

在我本地進(jìn)行測試例隆,F(xiàn)astThreadLocal的吞吐量是jdkThreadLocal的3倍左右。

備注: 由于FastThreadLocal內(nèi)容也非常非常多植影,而且有很多技巧裳擎,所以準(zhǔn)備后續(xù)專門在開一篇進(jìn)行串起來!K急摇!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羡微,一起剝皮案震驚了整個濱河市谷饿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妈倔,老刑警劉巖博投,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盯蝴,居然都是意外死亡毅哗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門捧挺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虑绵,“玉大人,你說我怎么就攤上這事闽烙〕峋Γ” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵黑竞,是天一觀的道長捕发。 經(jīng)常有香客問我,道長很魂,這世上最難降的妖魔是什么扎酷? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮遏匆,結(jié)果婚禮上法挨,老公的妹妹穿的比我還像新娘骤铃。我一直安慰自己,他們只是感情好坷剧,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布惰爬。 她就那樣靜靜地躺著,像睡著了一般惫企。 火紅的嫁衣襯著肌膚如雪撕瞧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天狞尔,我揣著相機(jī)與錄音丛版,去河邊找鬼。 笑死偏序,一個胖子當(dāng)著我的面吹牛页畦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播研儒,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼豫缨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了端朵?” 一聲冷哼從身側(cè)響起好芭,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冲呢,沒想到半個月后舍败,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡敬拓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年邻薯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乘凸。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡厕诡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翰意,到底是詐尸還是另有隱情木人,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布冀偶,位于F島的核電站醒第,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏进鸠。R本人自食惡果不足惜稠曼,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望客年。 院中可真熱鬧霞幅,春花似錦漠吻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扔傅,卻和暖如春耍共,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猎塞。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工试读, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荠耽。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓钩骇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铝量。 傳聞我的和親對象是個殘疾皇子倘屹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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