本篇內(nèi)容主要講解“ThreadLocal的結(jié)構(gòu)是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“ThreadLocal的結(jié)構(gòu)是什么”吧!
良慶ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!
在聊 ThreadLocal 前,先做前置知識鋪墊,談?wù)凧ava對象引用級別。
為了使程序能更靈活地控制對象生命周期,從 JDK1.2 版本開始,JDK把對象的引用級別由高到低分為強(qiáng)引用、軟引用、弱引用、虛引用四種級別。
強(qiáng)引用是我們最常見的對象,它屬于不可回收資源,垃圾回收器(后面簡稱G C)絕對不會回收它,即使是內(nèi)存不足,J V M寧愿拋出 OutOfMemoryErrorM 異常,使程序終止,也不會來回收強(qiáng)引用對象。
如果對象是軟引用,那它的性質(zhì)屬于可有可無,因?yàn)閮?nèi)存空間充足的情況下,G C不會回收它,但是內(nèi)存空間緊張,G C發(fā)現(xiàn)它僅有軟引用,就會回收該對象,所以軟引用對象適合作為內(nèi)存敏感的緩存對象。
只有對象僅被 WeakReference 引用,它才是弱引用級別對象,因?yàn)閷ο罂梢栽诙嗵幈灰茫?nbsp;WeakReference 引用的對象,它可能在其他處被強(qiáng)引用了。
顧名思義,虛引用形同虛設(shè),與其他幾種引用不同,虛引用不會決定對象的生命周期。
如果一個(gè)對象僅有虛引用,那它就和沒有任何引用一樣,任何時(shí)候都可能被 G C 回收。
ThreadLocal很多地方叫線程本地變量,也有些地方叫線程本地存儲,其實(shí)意思差不多。ThreadLocal為變量在每個(gè)線程中都創(chuàng)建了一個(gè)副本,每個(gè)線程可以訪問自己內(nèi)部的副本變量。
Thread類聲明了成員變量threadLocals,threadLocals才是真正的線程本地變量,因此每個(gè) Thread 都有自己的線程本地變量,所以線程本地變量擁有線程隔離特性,也就是天生的線程安全。
從上圖可以看到 threadLocals 成員變量類是 ThreadLocal.ThreadLocalMap,即是 ThreadLocal 提供的內(nèi)部類,因此 Thread 線程本地變量的創(chuàng)建、新增、獲取、刪除實(shí)現(xiàn)核心,必然是圍繞 threadLocals,所以開發(fā)者也是圍繞 threadLocals 實(shí)現(xiàn)功能,為了后續(xù)重復(fù)使用,還會對代碼實(shí)現(xiàn)進(jìn)行封裝復(fù)用,而 ThreadLocal 就是線程本地變量工具類,由 J D K 提供,線程本地變量的功能都已經(jīng)實(shí)現(xiàn)好了,開箱即用,造福廣大開發(fā)人員。
ThreadLocal常用的方法
set:為當(dāng)前線程設(shè)置變量,當(dāng)前ThreadLocal作為索引
get:獲取當(dāng)前線程變量,當(dāng)前ThreadLocal作為索引
initialValue(鉤子方法需要子類實(shí)現(xiàn)):賴加載形式初始化線程本地變量,執(zhí)行g(shù)et時(shí),發(fā)現(xiàn)線程本地變量為null,就會執(zhí)行initialValue的內(nèi)容
remove:清空當(dāng)前線程的ThreadLocal索引與映射的元素
現(xiàn)在總結(jié)出「本地線程變量的作用域,屬于當(dāng)前線程整個(gè)范圍,一個(gè)線程可以跨越多個(gè)方法使用本地線程變量」,當(dāng)你希望某些變量在某 Thread 的多個(gè)方法中共享 并保證線程安全,那就大膽的使用ThreadLocal(ps:一定要想清楚,是某個(gè)變量被Thread生命周期內(nèi)多個(gè)方法共享,還是多個(gè)Thread共享這個(gè)變量?。?。
先來看看User類實(shí)現(xiàn)的線程本地變量代碼
通過上圖,相信大伙對 ThreadLocalMap 結(jié)構(gòu)已經(jīng)非常清晰,不知有沒有細(xì)心的小伙伴發(fā)現(xiàn) ThreadLocal 竟被弱引用持有?
為什么ThreadLocal會被弱引用?這塊疑惑后面會給大伙安排的明明白白,最后上一張 ThreadLocalMap 源碼圖。
步驟如下
獲取當(dāng)前線程
獲取當(dāng)前線程的本地變量
線程本地變量沒有被創(chuàng)建,執(zhí)行setInitialValue方法進(jìn)行初始化,并返回value值
線程本地變量存在,ThreadLocal計(jì)算成索引從 本地線程變量 獲取Entry,如果Entry為null,執(zhí)行setInitialValue方法進(jìn)行初始化,并返回value值,否則通過Entry獲取value返回
步驟如下
獲取當(dāng)前線程
獲取線程本地變量
本地變量不為空,當(dāng)前ThreadLocal為索引設(shè)置映射的value,否則創(chuàng)建線程本地變量再做后續(xù)的設(shè)置操作
為什么 Entry 中對 ThreadLocal 使用弱引用?反問一句,如果使用強(qiáng)引用,會發(fā)生什么事情?
我們不知道 key 是什么,如何去獲取映射的value,同樣的道理,都沒有入口去獲取到ThreadContextTest.ThreadLoca,自然沒辦法獲取映射的Entry元素。
設(shè)計(jì)中采用Map結(jié)構(gòu)存儲數(shù)據(jù),卻不能通過key去獲取value,這設(shè)計(jì)明顯不合理,又因key、value值是強(qiáng)引用,導(dǎo)致 G C 無法回收,造成內(nèi)存溢出。
所以針對這種不合理的設(shè)計(jì)場景 J D K 做了優(yōu)化,對 Entry 中的 ThreadLocal 使用弱引用,當(dāng) G C 發(fā)現(xiàn)它僅有弱引用的時(shí)候,會進(jìn)行回收。
還沒結(jié)束,上面留了個(gè)小尾巴,大伙都知道 Entry 中對 ThreadLocal 使用弱引用,但value是強(qiáng)引用,如果出現(xiàn)上面提到的不合理場景,value值無法清理,最終內(nèi)存溢出。
其實(shí)value作為強(qiáng)引用設(shè)計(jì)屬于合理,如果用軟或弱引用,就出大問題了,程序跑著跑著突然get到了一個(gè)null,估計(jì)都得罵娘了,所以為解決內(nèi)存溢出問題 J D K提供remove方法,使開發(fā)人員可以選擇手動清理整個(gè)Entry元素,防止內(nèi)存溢出。
還記的之前說過嗎?線程本地變量的生命周期與線程綁定,一般線程的生命周期比較短,線程結(jié)束時(shí),線程本地變量自然就銷毀了,軟引用與 remove 會不會有點(diǎn)多余了?
業(yè)務(wù)瞬息萬變,大部分情況來說線程的生命周期比較短,但也業(yè)務(wù)場景會導(dǎo)致線程的生命周期較長,甚至可能線程無限循環(huán)執(zhí)行,這些是你沒辦法預(yù)料到的,數(shù)量一旦上來很容易內(nèi)存溢出,所以個(gè)人建議使用完之后及時(shí)清理ThreadLocal,理由如下
生命周期較長的線程場景
無限循環(huán)線程的場景
線程池場景(因?yàn)榫€程池可以復(fù)用線程,而且公司使用的框架可能會定制化線程池,你不能保證他會在線程池內(nèi)幫你remove)
到此,相信大家對“ThreadLocal的結(jié)構(gòu)是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
本文標(biāo)題:ThreadLocal的結(jié)構(gòu)是什么
標(biāo)題鏈接:http://chinadenli.net/article6/pghoig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站內(nèi)鏈、微信小程序、電子商務(wù)、營銷型網(wǎng)站建設(shè)、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)