京東一面:子執行緒如何獲取父執行緒 ThreadLocal 的值?我蒙了。。。
來源: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.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!