1. 程式人生 > >再次深入探究ThreadLocal原理及其使用方法,以此記錄

再次深入探究ThreadLocal原理及其使用方法,以此記錄

再次深入探究ThreadLocal,以此記錄。

為什麼說ThreadLocal叫做執行緒本地變數,因為ThreadLocal在每個執行緒中對該變數會建立一個執行緒共享變數,即每個執行緒內部都會有一個該變數,且線上程內部任何地方都可以使用,執行緒之間互不影響,這樣一來就不存線上程安全問題,也不會嚴重影響程式執行效能。

使用ThreadLocal不外乎3個方法:

threadLocal.set()

threadLocal.get()

threadLocal.remove()

顧名思義,分別是設定、獲取、移除當前執行緒中共享變數的值。

話不多說,直接上原始碼:

get()方法

跟入getMap(t)方法一探究竟

threadLocals

實際上就是一個ThreadLocalMap物件。

ThreadLocalMap其實就是在ThreadLocal中的一個內部類

setInitialValue()

createMap()

new一個ThreadLocalMap物件返回

set()和remove()方法

至此,真相大白。

真正儲存執行緒共享變數的地方是當前執行緒物件Thread的成員變數threadLocals,型別是ThreadLocal.ThreadLocalMap,k:ThreadLocal變數,v:執行緒共享變數

一開始,當前執行緒中的threadLocals為null,呼叫set()時,會對其中的threadLocals進行初始化,k就是ThreadLocal,v就是需要存放的執行緒共享變數

當需要的時候就可以從threadLocals中獲取到。

總結:

  1. 之所以說ThreadLocal執行緒安全,是因為所需要儲存的執行緒共享變數,都是存放在當前執行緒的threadLocals中。
  2. 選擇ThreadLocal作為threadLocals的key,是因為每個執行緒中可有多個threadLocal變數
  3. 在進行get之前,必須先set,否則會報空指標異常;

使用ThreadLocal的好處:

  1. 在多執行緒的環境中,保證當前執行緒的執行緒共享變數不被其他執行緒干擾,即不存線上程安全問題。
  2. 當執行緒死去時,threadLocals也就被銷燬。
  3. threadLocals的k-v數量由ThreadLocal物件的數量決定,比起Thread數量,ThreadLocal數量較少,效能更好。

關於ThreadLocalMap<ThreadLocal, Object>弱引用問題:

當執行緒沒有結束,但是ThreadLocal已經被回收,則可能導致執行緒中存在threadLocals的鍵值對,造成記憶體洩露。

(ThreadLocal被回收,ThreadLocal關聯的執行緒共享變數還存在)。

雖然ThreadLocal的get,set方法可以清除ThreadLocalMap中key為null的value,但是get,set方法在記憶體洩露後並不會必然呼叫。

為了防止弱引用問題(threadLocals鍵值對沒有被即使回收,造成記憶體洩漏)的出現,我們有兩種手段:

1、使用完執行緒共享變數後,顯示呼叫ThreadLocalMap.remove方法清除執行緒共享變數;

2、JDK建議ThreadLocal定義為private static,這樣ThreadLocal的弱引用問題則不存在了。

例子為證:

結果: