ThreadLocal
跨线程传递问题
父子线程间的传递问题
ThreadLocal
的子类InheritableThreadLocal
其实已经帮我们处理好了,通过这个组件可以实现父子线程之间的数据传递,在子线程中能够父线程中的ThreadLocal
本地变量。
我们发现InheritableThreadLocal
中createMap
,以及getMap
方法处理的对象不一样了,其中在ThreadLocal
中处理的是threadLocals
,而InheritableThreadLocal
中的是inheritableThreadLocals
。
代码的意思是在Thread获取先父亲线程parent(即要创建子线程的当前这个线程)。当父亲线程中对inherThreadLocals
进行了赋值,就会把当前线程的本地变量(也就是父线程的inherThreadLocals
)进行createInheritedMap
方法操作。查看源码createInheritedMap
方法,源码可知此操作就是将赋线程的threadLocalMap
传递给子线程。
参考:www.cnblogs.com/Nonnetta/p/…
使用异步线程池时的传递问题
这里有两种解决方案
参考Hystrix
中的回调方法
在SpringCloud
中的分布式链路跟踪时,traceId
如何在异步线程中传递traceId
呢?
看源码可以知道是通过:
Sluth
是通过实现HystrixConcurrencyStrategy
接口来解决traceId
异步传递的问题。Hystrix
在实际调用时,会调用HystrixConcurrencyStrategy
的wrapCallable
方法。因此,通过实现这个接口,在wrapCallable
中将traceId
存放起来(具体参见SleuthHystrixConcurrencyStrategy
)
线程池采用阿里的
通过inheritableThreadLocals
我们可以在父线程创建子线程的时候将Local中的值传递给子线程,这个特性已经能够满足大部分的需求了,但是还有一个很严重的问题是如果是在线程复用的情况下就会出问题,比如线程池中去使用inheritableThreadLocals
进行传值,因为inheritableThreadLocals
只是会再新创建线程的时候进行传值,线程复用并不会做这个操作,那么要解决这个问题就得自己去扩展线程类,实现这个功能。
不要忘记我们是做Java的哈,开源的世界有你需要的任何东西,下面我给大家推荐一个实现好了的Java库,是阿里开源的transmittable-thread-local。
GitHub地址:github.com/alibaba/tra…
主要功能就是解决在使用线程池等会缓存线程的组件情况下,提供ThreadLocal
值的传递功能,解决异步执行时上下文传递的问题。
JDK的InheritableThreadLocal
类可以完成父线程到子线程的值传递。但对于使用线程池等会缓存线程的组件的情况,线程由线程池创建好,并且线程是缓存起来反复使用的;这时父子线程关系的ThreadLocal
值传递已经没有意义,应用需要的实际上是把 任务提交给线程池时的ThreadLocal
值传递到任务执行时。
transmittable-thread-local使用方式分为三种,修饰Runnable和Callable,修饰线程池,Java Agent来修饰JDK线程池实现类