




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第深入淺出解析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)建出來后,對父線程中inheritThreadLocals的修改操作,對子線程不可見。
總結(jié)
ThreadLocal不可繼承,threadLocals是當(dāng)前線程的成員變量,在子線程中不可見。
InheritableThreadLocal可繼承,原理是:在新建子線程的時候,將父線程中inheritThreadLocals所有的entry拷貝給了子線程。
子線程創(chuàng)建出來后,對父線程中inheritThreadLocals的修改操作,對子線程不可見。
4.存在的內(nèi)存泄露問題
要充分理解ThreadLocal中存在的內(nèi)存泄露問題,需要有以下JVM對內(nèi)存管理的前置知識(這里篇幅問題就不補(bǔ)充了):
什么是內(nèi)存泄露?
什么是強(qiáng)引用?
什么是弱引用?
何時GC?
強(qiáng)引用和弱引用GC時的區(qū)別?
在分析上述ThreadLocalMap源碼的時候,注意到有一個小細(xì)節(jié),ThreadLocalMap的Entry繼承了WeakReferenceThreadLocal,也就是說Entry的key是一個對ThreadLocal的弱引用。問題來了,為什么這里要使用弱引用呢?
使用強(qiáng)引用會如何?
現(xiàn)在假設(shè)Entry的key是一個對ThreadLocal的強(qiáng)引用,當(dāng)ThreadLocal對象使用完后,外部的強(qiáng)引用不存在,但是因?yàn)楫?dāng)前線程對象中的threadLocals還持有ThreadLocal的強(qiáng)引用,而threadLocals的生命周期是和線程一致的,這個時候,如果沒有手動刪除,整個Entry就發(fā)生了內(nèi)存泄露。
使用弱引用會如何?
現(xiàn)在假設(shè)Entry的key是一個對ThreadLocal的弱引用,當(dāng)ThreadLocal對象使用完后,外部的強(qiáng)引用不存在,此時ThreadLocal對象只存在Entry中key對它的弱引用,在下次GC的時候,這個ThreadLocal對象就會被回收,導(dǎo)致key為null,此時value的強(qiáng)引用還存在,但是value已經(jīng)不會被使用了,如果沒有手動刪除,那么這個Entry中的key就會發(fā)生內(nèi)存泄露。
使用弱引用還有一些好處,那就是,當(dāng)key為null時,ThreadLocalMap中最多存在一個key為null,并且當(dāng)調(diào)用set(),get(),remove()這些方法的時候,是會清除掉key為null的entry的。
set()、get()、remove()方法中相關(guān)實(shí)現(xiàn)
從下可以發(fā)現(xiàn),set方法首先會進(jìn)入一個循環(huán)。
在這個循環(huán)中,會遍歷整個Entry數(shù)組。直到遇到一個空的entry,退出循環(huán)。
當(dāng)遇到已存在的key'時,會直接替換value,然后返回。
當(dāng)遇到key為空的entry的時候,會直接將當(dāng)前的entry存在這個過時的entry中,然后返回。
通過這個方法的源碼可以看出,key為null的那個entry實(shí)際上遲早會被替換成新的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;
//替換過時的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)]){
//清除過時的key
if(e.get()==key){
e.clear();
expungeStaleEntry(i);
return;
ThreadLocal如果對ThreadLocalMap的key使用強(qiáng)引用,那么會存在整個entry發(fā)生內(nèi)存泄露的問題,如果不手動清除,那么這個不被使用的entry會一直存在。
ThreadLocal如果對ThreadLocalMap的key使用弱引用,那么可能會存在一個entry的value發(fā)生內(nèi)存泄露,但是在調(diào)用set(),get(),remove()方法時,key為null的entry會被清除掉。
發(fā)生內(nèi)存泄露最根本的原因是:threadLocals的生命周期是和線程一致的。
每次使用完ThreadLocal對象后,必須調(diào)用它的remove()方法清除數(shù)據(jù)。
5.ThreadLocal應(yīng)用
ThreadLocal把數(shù)據(jù)存放到線程本地,解決了線程安全問題,沒有使用鎖,直接訪問線程本地變量,效率較高(空間換時間。)
同時thr
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 保護(hù)地球題庫及答案
- 版圖知識題目及答案
- 2025年職業(yè)技能培訓(xùn)在鄉(xiāng)村振興中的農(nóng)村教育質(zhì)量提升策略研究報(bào)告
- 安全員崗位試題及答案
- 罕見病藥物研發(fā)激勵政策與產(chǎn)業(yè)政策協(xié)同推進(jìn)報(bào)告
- 智能化環(huán)境監(jiān)測在環(huán)境法律法規(guī)執(zhí)行中的數(shù)據(jù)質(zhì)量控制與監(jiān)督
- 安全技術(shù)概論試題及答案
- 針對2025年運(yùn)動健身人群的健康功能性飲料市場前景研究報(bào)告
- 2025年鄉(xiāng)村文化旅游與鄉(xiāng)村旅游特色村寨建設(shè)報(bào)告
- 產(chǎn)婦護(hù)理技能培訓(xùn)課件
- 卷煙工廠MES系統(tǒng)技術(shù)方案
- 輥壓機(jī)培訓(xùn)ppt課件
- 全國醫(yī)療服務(wù)價(jià)格項(xiàng)目規(guī)范(試行)
- 譯林小學(xué)英語5B教材分析
- 江蘇省常州市2024屆高一數(shù)學(xué)下學(xué)期期末質(zhì)量調(diào)研試題(含解析)
- 新標(biāo)準(zhǔn)大學(xué)英語(第二版)綜合教程2 Unit 1 A篇練習(xí)答案及課文翻譯
- 冀教版英語小升初模擬試卷
- 食品用塑料包裝容器工具等制品生產(chǎn)許可審查細(xì)則
- 財(cái)政部金融企業(yè)不良資產(chǎn)批量轉(zhuǎn)讓管理辦法(財(cái)金[2012]6號)
- 物流供應(yīng)商運(yùn)作考評標(biāo)準(zhǔn)
- 招標(biāo)投標(biāo)活動異議和投訴處理工作規(guī)范
評論
0/150
提交評論