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

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

pri span 理解 wid spl child -s 應該 bsp

上一篇文章中對ThreadLocal進行了詳盡的介紹,另外還有一個類: InheritableThreadLocal 他是ThreadLocal的子類,那麽這個類又有什麽作用呢? 技術分享圖片

測試代碼

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則能夠獲取到值 技術分享圖片 結論: 在子線程中,可以獲取到父線程的InheritableThreadLocal類型變量的值,而不能獲取到ThreadLocal類型變量的值
對於ThreadLocal我們已經有了詳盡的分析,在Thread中有一個map,以ThreadLocal類型的變量作為key 在子線程中,get方法自然是獲取子線程中的map,很顯然,子線程中的map並沒有設置任何值,所以初始值null被讀取出來 但是,InheritableThreadLocal為什麽能夠讀取出來?

原理分析

在Thread類中,有一個ThreadLocal.ThreadLocalMap類型的變量:inheritableThreadLocals,他的類型同Thread內部的threadLocals變量 技術分享圖片 在Thread的init方法中,有一段初始化設置(應該還記得,這個init方法是所有的Thread對象創建的必經之路) 下面為部分代碼片段拼接 技術分享圖片 從上面的這個方法可以很清晰的看得到 如果parent的inheritableThreadLocals不是null,那麽就會將當前線程的inheritableThreadLocals設置為parent的inheritableThreadLocals parent是什麽?之前也說過了,就是創建這個線程的線程,也就是平時說的父線程 所以說 借助於inheritableThreadLocals,可以實現,創建線程向被創建線程數據傳遞 看下下面的方法 邏輯很清晰,創建了一個ThreadLocalMap inheritableThreadLocals就是ThreadLocalMap類型的 簡單理解:這個創建的ThreadLocalMap就是根據入參的ThreadLocalMap,拷貝創建一份 技術分享圖片 小結: Thread對象,通過內部的 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; 維護從父線程(創建該線程的線程)繼承而來的數據 原理就是在創建線程時,如果當前線程的inheritableThreadLocals不為null,那麽將會復制一份保存在自己的ThreadLocal.ThreadLocalMap inheritableThreadLocals中

InheritableThreadLocal類解析

對比下 下面的兩幅圖片,上面為Thread中的相關方法 下圖為InheritableThreadLocal中的三個方法 很顯然,InheritableThreadLocal作為子類,重寫了這幾個方法 技術分享圖片 技術分享圖片 通過對getMap和createMap方法的重寫,可以看得出來,只是內部操作的變量發生了變化,從threadLocals轉換為inheritableThreadLocals 而對於childValue方法,還記得剛才的構造方法麽(看註釋called only by createInheritedMap) 也就是說在父線程創建子線程,初始化InheritableThreadLocal時會用到 技術分享圖片

總結

InheritableThreadLocal的核心概念仍舊是ThreadLocal.ThreadLocalMap以及ThreadLocal InheritableThreadLocal是 ThreadLocal的子類 在Thread內部通過維護 ThreadLocal.ThreadLocalMap inheritableThreadLocals 進行父子線程數據的傳遞 而這個數據則是通過在創建Thread對象的時候,借助於內部的init方法,調用createInheritedMap方法,從父線程(當前創建線程)中復制的一份 後續的數據讀取解析,則是通過inheritableThreadLocals變量,與內部的那個threadLocals沒有什麽關系 換個思路理解,他就是另外一個ThreadLocal,假定Thread定義了兩個“ThreadLocal“,其中一個在創建線程的時候會從父線程復制一份 只不過從實現上、以及邏輯上,他繼承了ThreadLocal而已,然後覆蓋了幾個方法 原文地址:InheritableThreadLocal類原理簡介使用 父子線程傳遞數據詳解 多線程中篇(十七)

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