終於明白阿里百度這樣的大公司,為什麼面試經常拿ThreadLocal考驗求職者了

愛開發V發表於2020-02-06

點選上面↑「愛開發」關注我們

每晚10點,捕獲技術思考和創業資源洞察

什麼是ThreadLocal

ThreadLocal是一個本地執行緒副本變數工具類,各個執行緒都擁有一份執行緒私有的資料,執行緒之間的變數互不干擾,在高併發場景下,可以實現無狀態的呼叫。

ThreadLocal提供了執行緒安全的另一種思路,我們平常說的執行緒安全主要是保證共享資料的併發訪問問題,通過sychronized鎖或者CAS無鎖策略來保證資料的一致性。

ThreadLocal結構圖

640?wx_fmt=jpeg

從上面的結構圖,我們已經窺見ThreadLocal的核心機制:

  • 每個Thread執行緒內部都有一個Map。
  • Map裡面儲存執行緒本地物件(key)和執行緒的變數副本(value)
  • Thread內部的Map是由ThreadLocal維護的,由ThreadLocal負責向map獲取和設定執行緒的變數值。

對於不同的執行緒,每次獲取副本值時,別的執行緒並不能獲取到當前執行緒的副本值,形成了副本的隔離,彼此之間互不干擾。

我們來看個例子。

下面的例子有3個執行緒[thread#1],[thread#2],[thread#3]修改類變數initValue,當類變數是ThreadLocal的時候3個執行緒修改的值互不影響,列印的結果都是66

640?wx_fmt=jpeg

上面的例子3個執行緒是如果做到同時獨立修改變數的,答案就在ThreadLocal的set(),get()方法裡面.

下面我們再來看看ThreadLocal

ThreadLocal類提供如下幾個核心方法:

640?wx_fmt=jpeg

  • get()方法用於獲取當前執行緒的副本變數值。
  • set()方法用於儲存當前執行緒的副本變數值。
  • initialValue()為當前執行緒初始副本變數值。
  • remove()方法移除當前前程的副本變數值。

get()方法

640?wx_fmt=jpeg

  1. 獲取當前執行緒的ThreadLocalMap物件threadLocals
  2. 從map中獲取執行緒儲存的K-V Entry節點。
  3. 從Entry節點獲取儲存的Value副本值返回。
  4. map為空的話返回初始值null,即執行緒變數副本為null,需要注意的是在使用中要判斷是否為空指標NullPointerException。

set()方法

640?wx_fmt=jpeg

  1. 獲取當前執行緒的成員變數map
  2. map非空,則重新將ThreadLocal和新的value副本放入到map中。
  3. map空,則對執行緒的成員變數ThreadLocalMap進行初始化建立,並將ThreadLocal和value副本放入map中。

remove()方法

640?wx_fmt=jpeg

Thread執行緒內部的Map在類中描述如下:

640?wx_fmt=jpeg

可以看到,這個ThreadLocalMap是執行緒中的變數,也就是說每個執行緒都是相互獨立的

640?wx_fmt=jpeg

應用場景

類似單例類TransactionSynchronizationManager,

RequestContextHolder中就是通過ThreadLocal儲存各自執行緒變數的副本,這樣就不需要重新建立類。

一個知識點延伸出這麼多知識點,關於弱引用、 記憶體優化等,不僅能考驗求職者的對該知識點的掌握程度,又能考驗求職者的知識面,難怪阿里百度這樣的大公司喜歡在面試時拿它來考驗求職者。

-END-

往期精選推薦

更關注精彩內容,請長按識別關注

相關文章