




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第深入淺出解析JavaThreadLocal原理staticThreadLocalStringlocalStr=newThreadLocal();
staticInheritableThreadLocalStringinheritableLocalStr=newInheritableThreadLocal();
publicstaticvoidmain(String[]args)throwsInterruptedException{
inheritableLocalStr.set("main線程第一次為inheritableLocalStr設(shè)置的值");
newThread(newRunnable(){
@Override
publicvoidrun(){
log.debug("子線程第一次訪問inheritableLocalStr:"+inheritableLocalStr.get());
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
log.debug("子線程第二次訪問inheritableLocalStr:"+inheritableLocalStr.get());
}).start();
Thread.sleep(500);
inheritableLocalStr.set("main線程第二次為inheritableLocalStr設(shè)置的值");
log.debug("main線程第二次為inheritableLocalStr賦值");
Thread.sleep(1000);
看下輸出:
可以發(fā)現(xiàn),子線程創(chuàng)建出來后,對(duì)父線程中inheritThreadLocals的修改操作,對(duì)子線程不可見。
總結(jié)
ThreadLocal不可繼承,threadLocals是當(dāng)前線程的成員變量,在子線程中不可見。
InheritableThreadLocal可繼承,原理是:在新建子線程的時(shí)候,將父線程中inheritThreadLocals所有的entry拷貝給了子線程。
子線程創(chuàng)建出來后,對(duì)父線程中inheritThreadLocals的修改操作,對(duì)子線程不可見。
4.存在的內(nèi)存泄露問題
要充分理解ThreadLocal中存在的內(nèi)存泄露問題,需要有以下JVM對(duì)內(nèi)存管理的前置知識(shí)(這里篇幅問題就不補(bǔ)充了):
什么是內(nèi)存泄露?
什么是強(qiáng)引用?
什么是弱引用?
何時(shí)GC?
強(qiáng)引用和弱引用GC時(shí)的區(qū)別?
在分析上述ThreadLocalMap源碼的時(shí)候,注意到有一個(gè)小細(xì)節(jié),ThreadLocalMap的Entry繼承了WeakReferenceThreadLocal,也就是說Entry的key是一個(gè)對(duì)ThreadLocal的弱引用。問題來了,為什么這里要使用弱引用呢?
使用強(qiáng)引用會(huì)如何?
現(xiàn)在假設(shè)Entry的key是一個(gè)對(duì)ThreadLocal的強(qiáng)引用,當(dāng)ThreadLocal對(duì)象使用完后,外部的強(qiáng)引用不存在,但是因?yàn)楫?dāng)前線程對(duì)象中的threadLocals還持有ThreadLocal的強(qiáng)引用,而threadLocals的生命周期是和線程一致的,這個(gè)時(shí)候,如果沒有手動(dòng)刪除,整個(gè)Entry就發(fā)生了內(nèi)存泄露。
使用弱引用會(huì)如何?
現(xiàn)在假設(shè)Entry的key是一個(gè)對(duì)ThreadLocal的弱引用,當(dāng)ThreadLocal對(duì)象使用完后,外部的強(qiáng)引用不存在,此時(shí)ThreadLocal對(duì)象只存在Entry中key對(duì)它的弱引用,在下次GC的時(shí)候,這個(gè)ThreadLocal對(duì)象就會(huì)被回收,導(dǎo)致key為null,此時(shí)value的強(qiáng)引用還存在,但是value已經(jīng)不會(huì)被使用了,如果沒有手動(dòng)刪除,那么這個(gè)Entry中的key就會(huì)發(fā)生內(nèi)存泄露。
使用弱引用還有一些好處,那就是,當(dāng)key為null時(shí),ThreadLocalMap中最多存在一個(gè)key為null,并且當(dāng)調(diào)用set(),get(),remove()這些方法的時(shí)候,是會(huì)清除掉key為null的entry的。
set()、get()、remove()方法中相關(guān)實(shí)現(xiàn)
從下可以發(fā)現(xiàn),set方法首先會(huì)進(jìn)入一個(gè)循環(huán)。
在這個(gè)循環(huán)中,會(huì)遍歷整個(gè)Entry數(shù)組。直到遇到一個(gè)空的entry,退出循環(huán)。
當(dāng)遇到已存在的key'時(shí),會(huì)直接替換value,然后返回。
當(dāng)遇到key為空的entry的時(shí)候,會(huì)直接將當(dāng)前的entry存在這個(gè)過時(shí)的entry中,然后返回。
通過這個(gè)方法的源碼可以看出,key為null的那個(gè)entry實(shí)際上遲早會(huì)被替換成新的entry。
privatevoidset(ThreadLocalkey,Objectvalue){
//Wedon'tuseafastpathaswithget()becauseitisat
//leastascommontouseset()tocreatenewentriesas
//itistoreplaceexistingones,inwhichcase,afast
//pathwouldfailmoreoftenthannot.
Entry[]tab=table;
intlen=tab.length;
inti=key.threadLocalHashCode(len-1);
for(Entrye=tab[i];
e!=null;
e=tab[i=nextIndex(i,len)]){
ThreadLocalk=e.get();
if(k==key){
e.value=value;
return;
//發(fā)現(xiàn)key為空
if(k==null){
replaceStaleEntry(key,value,i);
return;
tab[i]=newEntry(key,value);
intsz=++size;
if(!cleanSomeSlots(i,sz)sz=threshold)
rehash();
privatestaticintnextIndex(inti,intlen){
return((i+1len)i+1:0);
同理,可以看到在get方法中也存在:
privateEntrygetEntry(ThreadLocalkey){
inti=key.threadLocalHashCode(table.length-1);
Entrye=table[i];
if(e!=nulle.get()==key)
returne;
else
returngetEntryAfterMiss(key,i,e);
privateEntrygetEntryAfterMiss(ThreadLocalkey,inti,Entrye){
Entry[]tab=table;
intlen=tab.length;
while(e!=null){
ThreadLocalk=e.get();
if(k==key)
returne;
//替換過時(shí)的entry
if(k==null)
expungeStaleEntry(i);
else
i=nextIndex(i,len);
e=tab[i];
returnnull;
remove()方法中也是一樣:
privatevoidremove(ThreadLocalkey){
Entry[]tab=table;
intlen=tab.length;
inti=key.threadLocalHashCode(len-1);
for(Entrye=tab[i];
e!=null;
e=tab[i=nextIndex(i,len)]){
//清除過時(shí)的key
if(e.get()==key){
e.clear();
expungeStaleEntry(i);
return;
ThreadLocal如果對(duì)ThreadLocalMap的key使用強(qiáng)引用,那么會(huì)存在整個(gè)entry發(fā)生內(nèi)存泄露的問題,如果不手動(dòng)清除,那么這個(gè)不被使用的entry會(huì)一直存在。
ThreadLocal如果對(duì)ThreadLocalMap的key使用弱引用,那么可能會(huì)存在一個(gè)entry的value發(fā)生內(nèi)存泄露,但是在調(diào)用set(),get(),remove()方法時(shí),key為null的entry會(huì)被清除掉。
發(fā)生內(nèi)存泄露最根本的原因是:threadLocals的生命周期是和線程一致的。
每次使用完ThreadLocal對(duì)象后,必須調(diào)用它的remove()方法清除數(shù)據(jù)。
5.ThreadLocal應(yīng)用
ThreadLocal把數(shù)據(jù)存放到線程本地,解決了線程安全問題,沒有使用鎖,直接訪問線程本地變量,效率較高(空間換時(shí)間。)
同時(shí)thr
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 抖音短視頻IP角色開發(fā)與品牌合作推廣協(xié)議
- 國(guó)際賽事場(chǎng)館頂層廣告位租賃與國(guó)際賽事宣傳服務(wù)合同
- 綜合性商業(yè)廣場(chǎng)餐飲區(qū)特許經(jīng)營(yíng)合同
- 智能家居社區(qū)期房預(yù)售權(quán)益分割與物業(yè)服務(wù)協(xié)議
- 獨(dú)家專利許可補(bǔ)充協(xié)議
- 安徽省A10聯(lián)盟2024-2025學(xué)年高二下學(xué)期3月階段考生物學(xué)試題
- 2025至2031年中國(guó)雙梁電子琴架市場(chǎng)現(xiàn)狀分析及前景預(yù)測(cè)報(bào)告
- 2025至2030年雙脈沖電容儲(chǔ)能點(diǎn)焊機(jī)項(xiàng)目投資價(jià)值分析報(bào)告
- 2025至2030年中國(guó)純棉普梳紗市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)無工作臺(tái)皮帶式輸送機(jī)市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 合資公司成立可行性研究報(bào)告范文
- 2025年中國(guó)電子產(chǎn)品租賃行業(yè)市場(chǎng)占有率及投資前景預(yù)測(cè)分析報(bào)告
- 2025年中國(guó)亮白防蛀固齒牙膏市場(chǎng)調(diào)查研究報(bào)告
- 上甘嶺戰(zhàn)役課件
- 黑龍江省齊齊哈爾市普高聯(lián)誼校2022-2023學(xué)年高一下學(xué)期語文期末試卷(含答案)
- 名家班主任培訓(xùn):AI賦能與德育創(chuàng)新
- 公安治安管理培訓(xùn)
- 湖北省武漢市2025屆高中畢業(yè)生四月調(diào)研考試物理試題及答案(武漢四調(diào))
- 珠寶并購策略優(yōu)化-全面剖析
- 平面向量及其應(yīng)用 章末題型歸納總結(jié)(基礎(chǔ)篇)(10大題型)原卷版-2024-2025學(xué)年高一數(shù)學(xué)(人教A版必修第二冊(cè))
- 人教PEP版英語五年級(jí)下冊(cè) Unit 4 單元練習(xí)卷
評(píng)論
0/150
提交評(píng)論