來源:blog.csdn.net/weixin_44912855
最近微信羣裏一個網友分享了他京東一面的過程,我這裏分享給大家其中一道面試題。
京東一面」子線程如何獲取父線程ThreadLocal的值
子線程如何獲取父線程ThreadLocal的值
想要子線程獲取父線程中 ThreadLocal 中的值,需要其子類 InheritableThreadLocal 實現。
測試代碼如下:
public static void main(String[] args) throws InterruptedException {
Thread parentParent = new Thread(() -> {
ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(1);
InheritableThreadLocal<Integer> inheritableThreadLocal = new InheritableThreadLocal<>();
inheritableThreadLocal.set(2);
new Thread(() -> {
System.out.println("threadLocal=" + threadLocal.get());
System.out.println("inheritableThreadLocal=" + inheritableThreadLocal.get());
}).start();
}, "父線程");
parentParent.start();
}
運行結果如下:
子線程獲取父線程中 ThreadLocal 中的值
原理如下:
首先我們要知道 Thread類維護了兩個ThreadLocalMap
跟進 new Thread() 方法
其構造方法調用了init方法, init方法把inheritThreadLocals值設置爲了true
繼續跟進。
當inheritThreadLocals的值爲true並且其父線程的inheritableThreadLocals不爲null時, 把其父線程inheritableThreadLocals 賦值給當前線程的inheritableThreadLocals
這就是子線程可以獲取到父線程ThreadLocal值的關鍵。
繼續跟進 看看 InheritableThreadLocal 的get() 方法
get()方法沒什麼好看的,就是ThreadLocal的get()方法。
注意: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。
同理,getMap方法在當前調用者線程調用get方法的時候返回的也不是threadLocals而是inheritableThreadLocal。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這纔是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!