中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ThreadLocal的結構是什么

發布時間:2021-10-12 11:02:45 來源:億速云 閱讀:189 作者:iii 欄目:編程語言

本篇內容主要講解“ThreadLocal的結構是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“ThreadLocal的結構是什么”吧!

內容大綱

ThreadLocal的結構是什么

Java對象引用級別

在聊 ThreadLocal 前,先做前置知識鋪墊,談談Java對象引用級別。

為了使程序能更靈活地控制對象生命周期,從 JDK1.2 版本開始,JDK把對象的引用級別由高到低分為強引用、軟引用、弱引用、虛引用四種級別。

強引用 StrongReference

強引用是我們最常見的對象,它屬于不可回收資源,垃圾回收器(后面簡稱G C)絕對不會回收它,即使是內存不足,J V M寧愿拋出 OutOfMemoryErrorM 異常,使程序終止,也不會來回收強引用對象。

ThreadLocal的結構是什么

軟引用 SoftReference

如果對象是軟引用,那它的性質屬于可有可無,因為內存空間充足的情況下,G C不會回收它,但是內存空間緊張,G C發現它僅有軟引用,就會回收該對象,所以軟引用對象適合作為內存敏感的緩存對象。

ThreadLocal的結構是什么

只有對象僅被 WeakReference 引用,它才是弱引用級別對象,因為對象可以在多處被引用,所以 WeakReference 引用的對象,它可能在其他處被強引用了。

虛引用 PhantomReference

顧名思義,虛引用形同虛設,與其他幾種引用不同,虛引用不會決定對象的生命周期。

如果一個對象僅有虛引用,那它就和沒有任何引用一樣,任何時候都可能被 G C 回收。

ThreadLocal的結構是什么

ThreadLocal

ThreadLocal很多地方叫線程本地變量,也有些地方叫線程本地存儲,其實意思差不多。ThreadLocal為變量在每個線程中都創建了一個副本,每個線程可以訪問自己內部的副本變量。

ThreadLocal是什么

Thread類聲明了成員變量threadLocals,threadLocals才是真正的線程本地變量,因此每個 Thread 都有自己的線程本地變量,所以線程本地變量擁有線程隔離特性,也就是天生的線程安全。

ThreadLocal的結構是什么

從上圖可以看到 threadLocals 成員變量類是 ThreadLocal.ThreadLocalMap,即是 ThreadLocal 提供的內部類,因此 Thread 線程本地變量的創建、新增、獲取、刪除實現核心,必然是圍繞 threadLocals,所以開發者也是圍繞 threadLocals 實現功能,為了后續重復使用,還會對代碼實現進行封裝復用,而 ThreadLocal 就是線程本地變量工具類,由 J D K 提供,線程本地變量的功能都已經實現好了,開箱即用,造福廣大開發人員。

ThreadLocal常用的方法

  • set:為當前線程設置變量,當前ThreadLocal作為索引

  • get:獲取當前線程變量,當前ThreadLocal作為索引

  • initialValue(鉤子方法需要子類實現):賴加載形式初始化線程本地變量,執行get時,發現線程本地變量為null,就會執行initialValue的內容

  • remove:清空當前線程的ThreadLocal索引與映射的元素

ThreadLocal的結構是什么

現在總結出「本地線程變量的作用域,屬于當前線程整個范圍,一個線程可以跨越多個方法使用本地線程變量」,當你希望某些變量在某 Thread 的多個方法中共享 并保證線程安全,那就大膽的使用ThreadLocal(ps:一定要想清楚,是某個變量被Thread生命周期內多個方法共享,還是多個Thread共享這個變量!)。

ThreadLocal源碼

先來看看User類實現的線程本地變量代碼

ThreadLocal的結構是什么

通過上圖,相信大伙對 ThreadLocalMap 結構已經非常清晰,不知有沒有細心的小伙伴發現 ThreadLocal 竟被弱引用持有?

為什么ThreadLocal會被弱引用?這塊疑惑后面會給大伙安排的明明白白,最后上一張 ThreadLocalMap 源碼圖。

ThreadLocal的結構是什么

步驟如下

  1. 獲取當前線程

  2. 獲取當前線程的本地變量

  3. 線程本地變量沒有被創建,執行setInitialValue方法進行初始化,并返回value值

  4. 線程本地變量存在,ThreadLocal計算成索引從 本地線程變量 獲取Entry,如果Entry為null,執行setInitialValue方法進行初始化,并返回value值,否則通過Entry獲取value返回

initialValue方法

ThreadLocal的結構是什么

步驟如下

  1. 獲取當前線程

  2. 獲取線程本地變量

  3. 本地變量不為空,當前ThreadLocal為索引設置映射的value,否則創建線程本地變量再做后續的設置操作

remove 清除變量

ThreadLocal的結構是什么

為何采用弱引用

為什么 Entry 中對 ThreadLocal 使用弱引用?反問一句,如果使用強引用,會發生什么事情?

ThreadLocal的結構是什么

我們不知道 key 是什么,如何去獲取映射的value,同樣的道理,都沒有入口去獲取到ThreadContextTest.ThreadLoca,自然沒辦法獲取映射的Entry元素。

設計中采用Map結構存儲數據,卻不能通過key去獲取value,這設計明顯不合理,又因key、value值是強引用,導致 G C 無法回收,造成內存溢出。

所以針對這種不合理的設計場景 J D K 做了優化,對 Entry 中的 ThreadLocal 使用弱引用,當 G C 發現它僅有弱引用的時候,會進行回收。

remove背后的意義

還沒結束,上面留了個小尾巴,大伙都知道 Entry 中對 ThreadLocal 使用弱引用,但value是強引用,如果出現上面提到的不合理場景,value值無法清理,最終內存溢出。

其實value作為強引用設計屬于合理,如果用軟或弱引用,就出大問題了,程序跑著跑著突然get到了一個null,估計都得罵娘了,所以為解決內存溢出問題 J D K提供remove方法,使開發人員可以選擇手動清理整個Entry元素,防止內存溢出。

還記的之前說過嗎?線程本地變量的生命周期與線程綁定,一般線程的生命周期比較短,線程結束時,線程本地變量自然就銷毀了,軟引用與 remove 會不會有點多余了?

業務瞬息萬變,大部分情況來說線程的生命周期比較短,但也業務場景會導致線程的生命周期較長,甚至可能線程無限循環執行,這些是你沒辦法預料到的,數量一旦上來很容易內存溢出,所以個人建議使用完之后及時清理ThreadLocal,理由如下

  • 生命周期較長的線程場景

  • 無限循環線程的場景

  • 線程池場景(因為線程池可以復用線程,而且公司使用的框架可能會定制化線程池,你不能保證他會在線程池內幫你remove)

到此,相信大家對“ThreadLocal的結構是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永新县| 镇坪县| 望谟县| 乳源| 辛集市| 长沙市| 通化市| 阜城县| 陇川县| 连州市| 章丘市| 金阳县| 澄迈县| 通州区| 临海市| 南充市| 香河县| 宜都市| 大英县| 棋牌| 木兰县| 广宗县| 札达县| 南投县| 仪征市| 鸡泽县| 临猗县| 巨鹿县| 来凤县| 吉木萨尔县| 新邵县| 辉南县| 西乡县| 青浦区| 勃利县| 栖霞市| 米脂县| 滦南县| 大兴区| 金华市| 沙雅县|