一張圖解決ThreadLocal

血夜之末發表於2021-02-08

一張圖解決ThreadLocal

一、前言

年底梳理知識體系時,研究了一下ThreadLocal的原始碼,整理了一張核心圖。
想著,都走到這一步了,那就寫一篇深度解讀的文章吧。看過我之前文章的小夥伴都知道,我寫部落格,就喜歡寫點別人沒寫的。要麼就寫個結構比別人好的。什麼都不行,那就別寫了。自己留著看就好了。
然後發現了ThreadLocal原始碼解讀ThreadLocal可能引起的記憶體洩露這樣的優秀文章(兩篇文章合起來,就更完整了),它把我要說的,差不多都說了。
所以,我就決定從精簡(一張圖)與認知過程兩方面,寫一篇輔助學習ThreadLocal的文章。

二、核心圖

不囉嗦,核心圖直接貼上。
在這裡插入圖片描述

根據核心圖,已經對ThreadLocal瞭然於心的小夥伴,可以拿著圖片,溜了溜了。
還想聽我談談,我對ThreadLocal認知過程的小夥伴,可以留下來看看。

三、認知過程

話說,那是一個夜黑風高的夜晚,我躺在。。。
咳咳咳。抱歉,串場了。
最早接觸ThreadLocal的時候,是在看面試教程的時候。我聽到講師balabala講了一通,最後我腦海給ThreadLocal的第一印象就是,一個確保執行緒安全的執行緒變數(同一個變數,但每個執行緒都獨立)。這個印象伴隨了我大半年,反正我在那大半年也沒用過。。。

後來,在一次看技術文章的時候,又看到了一篇ThreadLocal的介紹。通篇看下來,這篇文章說的內容,除了我學過的,就是總結了一句ThreadLocal可以簡單看成一個Map<Thread, Object>。當時的我,還欣喜若狂,我終於懂得ThreadLocal的原理了。

再後來,我在微信的技術公眾號中,看到ThreadLocal的記憶體洩漏問題。那篇文章把這個問題說得非常嚴重,搞得好像這個問題導致了二戰爆發那麼嚴重。如果不懂這個問題,就不配參加面試,不配呼吸這個世界的美好空氣。。。幸好當時沒人知道,我不懂這個東西。然後我就趁著午休的時間,速度翻了翻這篇文章。看完之後,腦海中的印象就是,ThreadLocal中的map的key是WeakReference,可能被清除,導致對應的value記憶體洩漏

在接下來的小半年裡,我也曾奇怪,如果ThreadLocal是一個Map<Thread, Object>,那為什麼一個執行緒可以有多個ThreadLocal變數呢?為什麼設定ThreadLocal變數時,還需要設定範型型別呢?

直到在學習另一個課程時,講師提到棧封閉-ThreadLocal,才知道之前的認識是錯誤的。其實每個執行緒都有一個Map<ThreadLocal, Object>,這也解釋了我之前的兩個問題。但是當時由於工作與課程比較緊,還是沒有檢視原始碼。終究還是與ThreadLocal隔層紗。

最近臨近年底,整理自己的知識體系。這次打算好好整理整理,所以就仔細閱讀了ThreadLocal的原始碼。也知道之所以每個執行緒都有一個Map<ThreadLocal, Object>,是因為Thread有一個ThreadLocalMap(ThreadLocal內部類)變數。進而總結出了上面的核心圖。

四、總結

之所以提到ThreadLocal的認識過程,其實是想表達:

  • 認識是螺旋前進的
  • 如無必要,不要過於追求認識的深度
  • 想法要周全,執行要堅決

第一條的意思是,我們對某個事物的認識,往往伴隨著正確&錯誤之間的遊走。但是認識是在不斷加深,變得更加全面的。
至於第二條,如果一開始我就強求看原始碼,那一定是事倍功半的。那時候的我對範型,弱應用等都瞭解太淺,缺乏足夠的基礎,讓我一窺ThreadLocal的全貌。具體的反面教材,就是當時剛入Java坑的我,強行擼Spring原始碼。。。檣櫓灰飛煙滅啊。。。
第三條,在自己有想法的時候,需要周全想法。如果有了決策結果,就應該去堅決地貫徹它。

不得不說,溫故而知新啊。

願與諸君共進步。

參考

相關文章