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线程池实现类