黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

面試題首頁(yè) > 多線程面試題

ThreadLocal面試題

001什么是ThreadLocal?

從字面上理解ThreadLocal就是“線程局部變量”的意思。簡(jiǎn)單的說(shuō)就是,一個(gè)ThreadLocal在一個(gè)線程中是共享的,在不同線程之間又是隔離的(每個(gè)線程都只能看到自己線程的值)。
學(xué)習(xí)一個(gè)類之前我們需要了解一個(gè)類的API,這也是我們學(xué)習(xí)類的入口。而ThreadLocal類的API相當(dāng)簡(jiǎn)單。
在這里面比較重要的就是,get、set、remove了,這三個(gè)方法是對(duì)這個(gè)變量進(jìn)行操作的關(guān)鍵。set用于賦值操作,get用于獲取變量中的值,remove就是刪除當(dāng)前這個(gè)變量的值。需要注意的是initialValue方法會(huì)在第一次調(diào)用時(shí)被觸發(fā),用于初始化當(dāng)前變量值,例如在下列代碼中我們需要?jiǎng)?chuàng)建一個(gè)ThreadLocal,用于創(chuàng)建一個(gè)與線程綁定的Connection對(duì)象:

ThreadLocal connection = new ThreadLocal(){
? ? public Connection initialValue(){
? ? ? ? return DriverManager.getConnection(…);
? ? }
});

為什么我們將ThreadLocal說(shuō)成變量,我們姑且可以這么理解,每個(gè)ThreadLocal實(shí)例中都可以保存一個(gè)值(基本數(shù)據(jù)類型值或者引用類型的引用值),而內(nèi)部保存的值是可以修改的,而這樣的特性與變量的特性及其相似,變量不就是用來(lái)保存一個(gè)值的嗎?也就是說(shuō)每一個(gè)ThreadLocal實(shí)例就類似于一個(gè)變量名,不同的ThreadLocal實(shí)例就是不同的變量名,它們內(nèi)部會(huì)存有一個(gè)值(暫時(shí)這么理解)在后面的描述中所說(shuō)的“ThreadLocal變量或者是線程變量”代表的就是ThreadLocal類的實(shí)例。我們通過(guò)重寫initialValue方法指定ThreadLocal變量的初始值,默認(rèn)情況下initialValue返回的是null。
 

002ThreadLocal的具體實(shí)現(xiàn)?

接下來(lái)我們就來(lái)動(dòng)手實(shí)踐一下,來(lái)理解前面沒(méi)有理解的那句話:一個(gè)ThreadLocal在一個(gè)線程中是共享的,在不同線程之間又是隔離的(每個(gè)線程都只能看到自己線程的值)

public class ThreadLocalTest {
?? ?private static ThreadLocal<Integer> num = new ThreadLocal<Integer>() {
?? ??? ?// 重寫這個(gè)方法,可以修改“線程變量”的初始值,默認(rèn)是null
?? ??? ?@Override
?? ??? ?protected Integer initialValue() {
?? ??? ??? ?return 0;
?? ??? ?}
?? ?};
?
?? ?public static void main(String[] args) {
?? ??? ?// 創(chuàng)建一號(hào)線程
?? ??? ?new Thread(new Runnable() {
?? ??? ??? ?@Override
?? ??? ??? ?public void run() {
?? ??? ??? ??? ?// 在一號(hào)線程中將ThreadLocal變量設(shè)置為1
?? ??? ??? ??? ?num.set(1);
?? ??? ??? ??? ?System.out.println("一號(hào)線程中ThreadLocal變量中保存的值為:" + num.get());
?? ??? ??? ?}
?? ??? ?}).start();
?
?? ??? ?// 創(chuàng)建二號(hào)線程
?? ??? ?new Thread(new Runnable() {
?? ??? ??? ?@Override
?? ??? ??? ?public void run() {
?? ??? ??? ??? ?num.set(2);
?? ??? ??? ??? ?System.out.println("二號(hào)線程中ThreadLocal變量中保存的值為:" + num.get());
?? ??? ??? ?}
?? ??? ?}).start();
?
?? ??? ?//為了讓一二號(hào)線程執(zhí)行完畢,讓主線程睡500ms
?? ??? ?try {
?? ??? ??? ?Thread.sleep(500);
?? ??? ?} catch (InterruptedException e) {
?? ??? ??? ?// TODO Auto-generated catch block
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ??? ?
?? ??? ?System.out.println("主線程中ThreadLocal變量中保存的值:" + num.get());
?? ?}
}

上面的代碼中在類中創(chuàng)建了一個(gè)靜態(tài)的“ThreadLocal變量”,在主線程中創(chuàng)建兩個(gè)線程,在這兩個(gè)線程中分別設(shè)置ThreadLocal變量為1和2。然后等待一號(hào)和二號(hào)線程執(zhí)行完畢后,在主線程中查看ThreadLocal變量的值。
程序結(jié)果及分析:
程序結(jié)果重點(diǎn)看的是主線程輸出的是0,如果是一個(gè)普通變量,在一號(hào)線程和二號(hào)線程中將普通變量設(shè)置為1和2,那么在一二號(hào)線程執(zhí)行完畢后在打印這個(gè)變量,輸出的值肯定是1或者2(到底輸出哪一個(gè)由操作系統(tǒng)的線程調(diào)度邏輯有關(guān))。但使用ThreadLocal變量通過(guò)兩個(gè)線程賦值后,在主線程程中輸出的卻是初始值0。在這也就是為什么“一個(gè)ThreadLocal在一個(gè)線程中是共享的,在不同線程之間又是隔離的”,每個(gè)線程都只能看到自己線程的值,這也就是ThreadLocal的核心作用:實(shí)現(xiàn)線程范圍的局部變量。
 

003ThreadLocal的原理分析?

我們還是將最后結(jié)論擺在前面,每個(gè)Thread對(duì)象都有一個(gè)ThreadLocalMap,當(dāng)創(chuàng)建一個(gè)ThreadLocal的時(shí)候,就會(huì)將該ThreadLocal對(duì)象添加到該Map中,其中鍵就是ThreadLocal,值可以是任意類型。也就是說(shuō),想要存入的ThreadLocal中的數(shù)據(jù)實(shí)際上并沒(méi)有存到ThreadLocal對(duì)象中去,而是以這個(gè)ThreadLocal實(shí)例作為key存到了當(dāng)前線程中的一個(gè)Map中去了,獲取ThreadLocal的值時(shí)同樣也是這個(gè)道理。這也就是為什么ThreadLocal可以實(shí)現(xiàn)線程之間隔離的原因了。
總結(jié):
1)ThreadLocal的作用:實(shí)現(xiàn)線程范圍內(nèi)的局部變量,即ThreadLocal在一個(gè)線程中是共享的,在不同線程之間是隔離的。
2)ThreadLocal的原理:ThreadLocal存入值時(shí)使用當(dāng)前ThreadLocal實(shí)例作為key,存入當(dāng)前線程對(duì)象中的Map中去。最開(kāi)始在看源碼之前,我以為是以當(dāng)前線程對(duì)象作為key將對(duì)象存入到ThreadLocal中的Map中去。

004ThreadLocal和Synchonized區(qū)別?

兩者都用于解決多線程并發(fā)訪問(wèn)。但是ThreadLocal與synchronized有本質(zhì)的區(qū)別。Synchronized用于線程間的數(shù)據(jù)共享,而ThreadLocal則用于線程間的數(shù)據(jù)隔離。Synchronized是利用鎖的機(jī)制,使變量或代碼塊在某一時(shí)該只能被一個(gè)線程訪問(wèn)。而ThreadLocal為每一個(gè)線程都提供了變量的副本,使得每個(gè)線程在某一時(shí)間訪問(wèn)到的并不是同一個(gè)對(duì)象,這樣就隔離了多個(gè)線程對(duì)數(shù)據(jù)的數(shù)據(jù)共享。而Synchronized卻正好相反,它用于在多個(gè)線程間通信時(shí)能夠獲得數(shù)據(jù)共享。

005ThreadLocal內(nèi)存泄漏以及解決方案?

如果ThreadLocal沒(méi)有外部強(qiáng)引用,那么在發(fā)生垃圾回收的時(shí)候,ThreadLocal就必定會(huì)被回收,而ThreadLocal又作為Map中的key,ThreadLocal被回收就會(huì)導(dǎo)致一個(gè)key為null的entry,外部就無(wú)法通過(guò)key來(lái)訪問(wèn)這個(gè)entry,垃圾回收也無(wú)法回收,這就造成了內(nèi)存泄漏
解決方案:每次使用完ThreadLocal都調(diào)用它的remove()方法清除數(shù)據(jù),或者按照J(rèn)DK建議將ThreadLocal變量定義成private static,這樣就一直存在ThreadLocal的強(qiáng)引用,也就能保證任何時(shí)候都能通過(guò)ThreadLocal的弱引用訪問(wèn)到Entry的value值,進(jìn)而清除掉。

目錄

返回頂部
主站蜘蛛池模板: 国产精品日韩欧美一区二区 | 99国产在线观看 | 成 人网站免费 | 老司机精品99在线播放 | 亚洲黄色网址在线观看 | 欧洲另类一二三四区 | 99re久久| 日日操夜夜骑 | 国产污污视频 | 久久久网站亚洲第一 | 亚洲国产中文字幕 | 全免费午夜一级毛片真人 | ww亚洲ww在线观看国产 | 日本xxx18hd19hd | 波多野结衣日韩 | 免费黄在线观看 | 国产va欧美va在线观看 | 日本一区二区三区在线 视频 | 成年午夜视频免费观看视频 | 欧美黑人巨大硬xxx猛性 | 一本久道久久综合中文字幕 | 日日狠狠久久偷偷四色综合免费 | 美女网站视频黄 | 欧美人妖猛交 | 可以免费看的黄色片 | 一级无毛片 | 色多多污网站 | 成年男女免费视频 | 九九色视频在线观看 | 黄色片免费观看视频 | 永久网站www774777视频 | 深夜男人影院 | 久久精品5 | 草草国产成人免费视频 | 一级特级aaaa毛片免费观看 | 簧片免费视频 | 古代级a毛片在线 | 天天干天天干天天 | 最近最新中文字幕免费高清1 | 亚洲免费二区三区 | 欧美男同志videos |