京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))

最近微信群里一个网友分享了他京东一面的过程,我这里分享给大家其中一道面试题。
京东一面:子线程如何获取父线程ThreadLocal的值
子线程如何获取父线程ThreadLocal的值 京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

图片
想要子线程获取父线程中 ThreadLocal 中的值,需要其子类 InheritableThreadLocal 实现。
测试代码如下:

public static void main(String[] args) throws InterruptedException { Thread parentParent = new Thread(() -> { 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(); }

运行结果如下:
京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

子线程获取父线程中 ThreadLocal 中的值。另外,上周抽时间整理了一份简历资料,既包含简历撰写的要点,还收录了几位大佬的简历模板,感兴趣的小伙伴赶快来这里领取吧!
原理如下:
首先我们要知道 Thread类维护了两个ThreadLocalMap
京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

图片
跟进 new Thread() 方法
其构造方法调用了init方法, init方法把inheritThreadLocals值设置为了true
京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

图片
继续跟进。程序员专属的壁纸,关注公众号SpringForAll社区,回复:壁纸,即可领取高清无水印壁纸。
inheritThreadLocals的值为true并且其父线程的inheritableThreadLocals不为null时, 把其父线程inheritableThreadLocals赋值给当前线程的inheritableThreadLocals
京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

图片
这就是子线程可以获取到父线程ThreadLocal值的关键。推荐:上周抽时间整理了一份简历资料,既包含简历撰写的要点,还收录了几位大佬的简历模板,感兴趣的小伙伴赶快来这里领取吧!
继续跟进 看看InheritableThreadLocalget()方法
get()方法没什么好看的,就是ThreadLocal的get()方法。
京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))
文章图片

图片
注意:InheritableThreadLocal 对ThreadLocal 的getMap()方法进行重写
ThreadLocalMap getMap(Thread t) { //获取线程自己的变量threadLocals,并绑定到当前调用线程的成员变量threadLocals上 return t.threadLocals; }void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); //创建给ThreadLocalMap的table属性赋值,并且将firstValue放在数组首位。 }

createMap方法不仅创建了threadLocals,同时也将要添加的本地变量值添加到了threadLocals中。
InheritableThreadLocal类继承了ThreadLocal类,并重写了childValue、getMap、createMap方法。
其中createMap方法在被调用的时候,创建的是inheritableThreadLocal而不是threadLocals
【京东一面(子线程如何获取父线程 ThreadLocal 的值(我蒙了。。。))】同理,getMap方法在当前调用者线程调用get方法的时候返回的也不是threadLocals而是inheritableThreadLocal

    推荐阅读