transmittable-thread-local解析

這玩意我第一次用到是在用springcloud時候,有組員跟我說希望可以用線程池異步執行。本來沒啥問題,但是我們希望模塊之間傳遞traceId(方便日誌查詢),我們做法是把traceid放在threadlocal裏,然後feign請求時候再取出來帶到下一個模塊去,然後就出現問題了,最後用transmittable-thread-local解決了。

一、源碼解析

點開TransmittableThreadLocal類,查看它的set、get方法

第一步都是調用threadlocal的set、get方法,不同的是多了removeValue和addValue方法。點開看看。

代碼也很少,大致可以猜到有個倉庫叫holder來存儲或者刪除當前TransmittableThreadLocal,好了讓我們看看holder實現了哪些玩意。

這個類首先是靜態的,也就是說多個TransmittableThreadLocal共享。其次用了InheritableThreadlocal,因爲主線程寫了數據到holder,線程池子線程需要拿到所以用這個。然後InheritableThreadlocal裏頭是一個map,結構類似threadlocalmap,包括weakhashmap也是實現entry類似的功能。(這一塊都是我個人猜測作者的意思,並不是很確定)

====== 到此存儲部分介紹完了,接下里是介紹子線程裏如何拿出來 =====

看TtlRunnable類,我們執行runnable都會用這個類包一層,看看它的get方法

這裏我想說一下我看源碼的習慣,我喜歡由大到小這樣來看,意思是比如上圖的if塊,說實話我到現在都沒去看它是啥玩意,但是我知道這個不是主要流程,所以我們直接看TtlRunnable的構造方法。

其他都沒啥就是一個capture()方法,這個方法是在TransmittableThreadLocal類下的一個靜態內部類裏,由於import static所以不用寫類名(雖然優雅,但是做爲源碼我覺得還是類名+方法名才更清晰)。這個方法就是返回父類的holder值。初始化完了就開始調用run方法了,看看他對run方法做了什麼操作。

這裏也是最核心的部分,再堅持一下,這部分講完這篇廢話博客就結束了!

首先是先get獲取我們上面構造方法裏賦值的父類holder,然後一系列校驗(不是主線,跳!),然後有3個方法,replay、run、restore。我們先看run,run就是運行我們傳入的run方法。那麼我們可以推理出從holder裏拿出來並且賦值到子線程的過程就在replay裏!看看!

重點2塊:

1、for裏頭的,對當前holder進行備份並且刪除run方法開始後又插入的ttl

2、setTtlValuesTo,這個方法把值插入到子線程裏

然後我們再看看restore方法

跟上面的方法差不多,也不多做解釋。唯一解釋一下的就是這兩個方法的for循環裏功能其實就爲了一個目的,就是子線程執行過程中如果又新的ttl插入,那麼刪除,保證開始和結束時候狀態一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章