如何让子线程获取到父线程的ThreadLocal中的值

代码demo如下:

public static void main(String[] args) throws InterruptedException {
    Thread parentParent = new Thread(new Runnable() {
        @Override
        public void run() {
            ThreadLocal threadLocal = new ThreadLocal();
            threadLocal.set(1);
            InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
            inheritableThreadLocal.set(2);
            new Thread(() -> {
                System.out.println("threadLocal=" + threadLocal.get());
                System.out.println("inheritableThreadLocal=" + inheritableThreadLocal.get());
            }).start();
        }
    }, "父线程");
    parentParent.start();
}

运行结果如下:
在这里插入图片描述
可以发现,使用的InheritableThreadLocal对象,是可以让子线程获取到父线程设置到threadLocal中的值的。那么先看看InheritableThreadLocal是什么?可以发现
InheritableThreadLocal是ThreadLocal的子类,如下:
在这里插入图片描述
那为什么子线程能够获取到父线程设置在ThreadLocal中的值呢,跟进new Thread()方法中,如下:
在这里插入图片描述
继续跟进init方法(),如下:
在这里插入图片描述
会发现有个熟悉的参数被设置为了true,继续跟进去,如下:
在这里插入图片描述
发现有做个判断,只要参数inheritThreadLocals的值等于true以及父线程中的inheritableThreadLocals不为null,就会调用ThreadLocal.createInheritedMap()方法,把父线程的inheritableThreadLocals作为参传进去,然后把返回的结果再赋值到当前线程的inheritableThreadLocals变量中,接着看看inheritableThreadLocal.get()方法,如下:
在这里插入图片描述
会发现其实以上标记出的getMap()方法其实已经被子类InheritableThreadLocal类重写了,所以真实调用的getMap()方法如下:
在这里插入图片描述
所以返回的其实是子类的inheritableThreadLocal变量,而该变量其实是由父线程那传递过来再设值的,通过断点验证结果如下:
在这里插入图片描述
所以子线程才能拿到2这个结果。

那么值又是怎么设置进父线程的inheritableThreadLocals变量中的呢,跟进inheritableThreadLocal.set()方法,如下:
在这里插入图片描述
然后会发现createMap()方法,其实子类InheritableThreadLocal也做了重写,有自己的实现,如下:
在这里插入图片描述
所以此时就可以明白值是怎么被设置进线程的inheritableThreadLocals属性。

总结

其实对以上的逻辑进行梳理,可以发现子线程能够获取到父线程的ThreadLocal中的值,是因为子类InheritableThreadLocal重写了一些方法,同时初始化线程时,会根据一定的参数,来决定父线程需不需要把自己的inheritableThreadLocals属性中的值拷贝一份赋值给子线程。

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/107558283