1、父子線程間的傳遞問題
ThreadLocal的子類InheritableThreadLocal其實已經幫我們處理好了,通過這個組件可以實現父子線程之間的數據傳遞,在子線程中能夠父線程中的ThreadLocal本地變量。
我們發現InheritableThreadLocal中createMap,以及getMap方法處理的對象不一樣了,其中在ThreadLocal中處理的是threadLocals,而InheritableThreadLocal中的是inheritableThreadLocals。
代碼的意思是在Thread獲取先父親線程parent(即要創建子線程的當前這個線程)。當父親線程中對inherThreadLocals進行了賦值,就會把當前線程的本地變量(也就是父線程的inherThreadLocals)進行createInheritedMap方法操作。查看源碼createInheritedMap方法,源碼可知此操作就是將賦線程的threadLocalMap傳遞給子線程。
參考:https://www.cnblogs.com/Nonnetta/p/10175662.html
2、使用異步線程池時的傳遞問題
這里有兩種解決方案
1、參考Hystrix中的回調方法
在SpringCloud中的分布式鏈路跟蹤時,traceId如何在異步線程中傳遞traceId呢?
看源碼可以知道是通過:
Sluth是通過實現HystrixConcurrencyStrategy接口來解決traceId異步傳遞的問題。Hystrix在實際調用時,會調用HystrixConcurrencyStrategy的wrapCallable方法。因此,通過實現這個接口,在wrapCallable中將traceId存放起來(具體參見SleuthHystrixConcurrencyStrategy)
https://blog.csdn.net/yaowwwww7071/article/details/85769505
2、線程池采用阿里的
通過inheritableThreadLocals我們可以在父線程創建子線程的時候將Local中的值傳遞給子線程,這個特性已經能夠滿足大部分的需求了,但是還有一個很嚴重的問題是如果是在線程復用的情況下就會出問題,比如線程池中去使用inheritableThreadLocals 進行傳值,因為inheritableThreadLocals 只是會再新創建線程的時候進行傳值,線程復用並不會做這個操作,那么要解決這個問題就得自己去擴展線程類,實現這個功能。
不要忘記我們是做Java的哈,開源的世界有你需要的任何東西,下面我給大家推薦一個實現好了的Java庫,是阿里開源的transmittable-thread-local。
GitHub地址:https://github.com/alibaba/transmittable-thread-local
主要功能就是解決在使用線程池等會緩存線程的組件情況下,提供ThreadLocal值的傳遞功能,解決異步執行時上下文傳遞的問題。
JDK的InheritableThreadLocal類可以完成父線程到子線程的值傳遞。但對於使用線程池等會緩存線程的組件的情況,線程由線程池創建好,並且線程是緩存起來反復使用的;這時父子線程關系的ThreadLocal值傳遞已經沒有意義,應用需要的實際上是把 任務提交給線程池時的ThreadLocal值傳遞到任務執行時。
transmittable-thread-local使用方式分為三種,修飾Runnable和Callable,修飾線程池,Java Agent來修飾JDK線程池實現類