Last updated
Last updated
ThreadLocal是线程私有变量,每个线程均有一个私有的ThreadLocal变量,为在复杂场景下的传值提供了一种便捷的方式。
比如
但是ThreadLocal只能解决在某一个线程内的变量set/get,假如现在我们想在子线程中获取父线程中的ThreadLoca变量的值,怎么办?
什么是父子线程
在A线程中,创建并启动了线程B,那么A就是B的父线程,B就是A的子线程;
对某线程而言,至多有一个父线程,可以有多个子线程。
我们期望在[2]处输出value:::value-in-parent
,显然ThreadLocal
无法满足需求。JDK中提供了InheritableThreadLocal
,将上面代码中的ThreadLocal
替换为InheritableThreadLocal
,其他内容保持不变:
可以看到,主线程中的local变量的值被传递到了子线程中,这就解决了无法在子线程中获取父线程ThreadLocal值的问题。此外,上面的代码中标出的(*)位置处,改变了子线程中local值,但父线程中的local值没有改变,这就是说,子线程仅仅是获取了父线程中local值作为自己的初始值,但子线程改变自己的local值,并不会影响父线程的local值。
但是,在实际项目中,我们一般不会直接通过new Thread这种方式使用线程,而是使用线程池,这样就会对线程重复利用。此时,假如向线程池提交多个任务,这些任务会改变所在线程的threadlocal值,但是新提交的任务又必须使用父线程中的值,怎么办?我们还是使用Inheritable来试一下,看它能不能满足需求:
我们期望[4]处获取的值为value:::value-in-parent
,但实际却是value:::value-in-runnable1
,这是因为,我们的线程池中只有一个线程(假设为A),runnable1执行完毕之后,将A线程的local值设为了value:::value-in-runnable1
,runnable2仍然是在A线程执行,那么[4]处就是runnable1改变之后的local值。
可见,上面的[4]处输出的值为父线程中的local值,满足了我们的需求。
该问题的解决方案为阿里开源的,上述问题的解决代码如下: