InheritableThreadLocal類原理簡介使用 父子線程傳遞數據詳解 多線程中篇(十八)

 
上一篇文章中對ThreadLocal進行了詳盡的介紹,另外還有一個類:
InheritableThreadLocal
他是ThreadLocal的子類,那麼這個類又有什麼做用呢?
image_5c77364a_33e3
 

測試代碼

 

public class T25 {

public static void main(String[] args) {

//主線程中賦值
ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();

InheritableThreadLocal<String> stringInheritableThreadLocal = new InheritableThreadLocal<>();

stringThreadLocal.set("ThreadLocal string");
stringInheritableThreadLocal.set("InheritableThreadLocal string");

//子線程中分別打印兩個變量的信息
new Thread(() -> {
System.out.println(
Thread.currentThread().getName() + " ThreadLocal value :" + stringThreadLocal.get());
System.out.println(Thread.currentThread().getName() + " InheritableThreadLocal value :"
+ stringInheritableThreadLocal.get());
}).start();

}
}
在上面的測試代碼中,主線程中建立了兩個變量,類型分別爲:ThreadLocal和InheritableThreadLocal
而後在主線程中建立了一個新的線程
在新的線程中,嘗試獲取他們的值
從打印信息能夠看得出來
對於ThreadLocal獲取的值爲null,而對於InheritableThreadLocal則可以獲取到值
image_5c77364a_7c3
結論:
在子線程中,能夠獲取到父線程的InheritableThreadLocal類型變量的值,而不能獲取到ThreadLocal類型變量的值
對於ThreadLocal咱們已經有了詳盡的分析,在Thread中有一個map,以ThreadLocal類型的變量做爲key
在子線程中,get方法天然是獲取子線程中的map,很顯然,子線程中的map並無設置任何值,因此初始值null被讀取出來
可是,InheritableThreadLocal爲何可以讀取出來?

原理分析

在Thread類中,有一個ThreadLocal.ThreadLocalMap類型的變量:inheritableThreadLocals,他的類型同Thread內部的threadLocals變量
image_5c77364a_13aa
在Thread的init方法中,有一段初始化設置(應該還記得,這個init方法是全部的Thread對象建立的必經之路)
下面爲部分代碼片斷拼接
image_5c77364a_2ad4
從上面的這個方法能夠很清晰的看獲得
若是parent的inheritableThreadLocals不是null,那麼就會將當前線程的inheritableThreadLocals設置爲parent的inheritableThreadLocals
parent是什麼?以前也說過了,就是建立這個線程的線程,也就是平時說的父線程
因此說
藉助於inheritableThreadLocals,能夠實現,建立線程向被建立線程數據傳遞
看下下面的方法
邏輯很清晰,建立了一個ThreadLocalMap
inheritableThreadLocals就是ThreadLocalMap類型的
簡單理解:這個建立的ThreadLocalMap就是根據入參的ThreadLocalMap,拷貝建立一份
image_5c77364a_68
小結:
Thread對象,經過內部的
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
維護從父線程(建立該線程的線程)繼承而來的數據
原理就是在建立線程時,若是當前線程的inheritableThreadLocals不爲null,那麼將會複製一份保存在本身的ThreadLocal.ThreadLocalMap inheritableThreadLocals中

InheritableThreadLocal類解析

對比下 下面的兩幅圖片,上面爲Thread中的相關方法
下圖爲InheritableThreadLocal中的三個方法
很顯然,InheritableThreadLocal做爲子類,重寫了這幾個方法
image_5c77364a_7073
 
image_5c77364b_73a8
經過對getMap和createMap方法的重寫,能夠看得出來,只是內部操做的變量發生了變化,從threadLocals轉換爲inheritableThreadLocals
而對於childValue方法,還記得剛纔的構造方法麼(看註釋called only by createInheritedMap)
也就是說在父線程建立子線程,初始化InheritableThreadLocal時會用到
image_5c77364b_45a1

總結

InheritableThreadLocal的核心概念仍舊是ThreadLocal.ThreadLocalMap以及ThreadLocal
InheritableThreadLocal是 ThreadLocal的子類
在Thread內部經過維護    ThreadLocal.ThreadLocalMap inheritableThreadLocals 進行父子線程數據的傳遞
而這個數據則是經過在建立Thread對象的時候,藉助於內部的init方法,調用createInheritedMap方法,從父線程(當前建立線程)中複製的一份
後續的數據讀取解析,則是經過inheritableThreadLocals變量,與內部的那個threadLocals沒有什麼關係
換個思路理解,他就是另一個ThreadLocal,假定Thread定義了兩個「ThreadLocal「,其中一個在建立線程的時候會從父線程複製一份
只不過從實現上、以及邏輯上,他繼承了ThreadLocal而已,而後覆蓋了幾個方法
 
相關文章
相關標籤/搜索