您好,登錄后才能下訂單哦!
這篇文章主要介紹“Inheritable中的ThreadLocal是什么”,在日常操作中,相信很多人在Inheritable中的ThreadLocal是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Inheritable中的ThreadLocal是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
1、簡介 在上一篇 ThreadLocal詳解 中,我們詳細介紹了ThreadLocal原理及設計,從源碼層面上分析了ThreadLocal。但由于ThreadLocal設計之初就是為了綁定當前線程,如果希望當前線程的ThreadLocal能夠被子線程使用,實現方式就會相當困難(需要用戶自己在代碼中傳遞)。在此背景下,InheritableThreadLocal應運而生。
Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.
2、應用 調用鏈追蹤:在調用鏈系統設計中,為了優化系統運行速度,會使用多線程編程,為了保證調用鏈ID能夠自然的在多線程間傳遞,需要考慮ThreadLocal傳遞問題(大多數系統會使用線程池技術,這已經不僅僅是InheritableThreadLocal能夠解決的了,我會在另外一篇文章中介紹相關技術實現)。
3、InheritableThreadLocal類 InheritableThreadLocal類重寫了ThreadLocal的3個函數:
`/** * 該函數在父線程創建子線程,向子線程復制InheritableThreadLocal變量時使用 */ protected T childValue(T parentValue) { return parentValue; } /** * 由于重寫了getMap,操作InheritableThreadLocal時, * 將只影響Thread類中的inheritableThreadLocals變量, * 與threadLocals變量不再有關系 */ ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * 類似于getMap,操作InheritableThreadLocal時, * 將只影響Thread類中的inheritableThreadLocals變量, * 與threadLocals變量不再有關系 */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); }`
注意:由于重寫了getMap()和createMap()兩個函數,所以當
4、線程間傳值實現原理 說到InheritableThreadLocal,還要從Thread類說起:
public class Thread implements Runnable { ......(其他源碼) /* * 當前線程的ThreadLocalMap,主要存儲該線程自身的ThreadLocal */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal,自父線程集成而來的ThreadLocalMap, * 主要用于父子線程間ThreadLocal變量的傳遞 * 本文主要討論的就是這個ThreadLocalMap */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ......(其他源碼)
}`
Thread類中包含 threadLocals 和 inheritableThreadLocals 兩個變量,其中 inheritableThreadLocals 即主要存儲可自動向子線程中傳遞的ThreadLocal.ThreadLocalMap。 接下來看一下父線程創建子線程的流程,我們從最簡單的方式說起:
4.1、用戶創建Thread, Thread thread = new Thread();
4.2、Thread創建
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
4.3、Thread初始化
/** * 默認情況下,設置inheritThreadLocals可傳遞 */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } /** * 初始化一個線程. * 此函數有兩處調用, * 1、上面的 init(),不傳AccessControlContext,inheritThreadLocals=true * 2、傳遞AccessControlContext,inheritThreadLocals=false */ private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { ......(其他代碼) if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); ......(其他代碼) }`
可以看到,采用默認方式產生子線程時,inheritThreadLocals=true;若此時父線程inheritableThreadLocals不為空,則將父線程inheritableThreadLocals傳遞至子線程。
4.4、ThreadLocal.createInheritedMap 讓我們繼續追蹤createInheritedMap:
`static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } /** * 構建一個包含所有parentMap中Inheritable ThreadLocals的ThreadLocalMap * 該函數只被 createInheritedMap() 調用. */ private ThreadLocalMap(ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); // ThreadLocalMap 使用 Entry[] table 存儲ThreadLocal table = new Entry[len]; // 逐一復制 parentMap 的記錄 for (int j = 0; j < len; j++) { Entry e = parentTable[j]; if (e != null) { @SuppressWarnings("unchecked") ThreadLocal<Object> key = (ThreadLocal<Object>) e.get(); if (key != null) { // 可能會有同學好奇此處為何使用childValue,而不是直接賦值, // 畢竟childValue內部也是直接將e.value返回; // 個人理解,主要為了減輕閱讀代碼的難度 Object value = key.childValue(e.value); Entry c = new Entry(key, value); int h = key.threadLocalHashCode & (len - 1); while (table[h] != null) h = nextIndex(h, len); table[h] = c; size++; } } } }`
從ThreadLocalMap可知,子線程將parentMap中的所有記錄逐一復制至自身線程。
5、總結 InheritableThreadLocal主要用于子線程創建時,需要自動繼承父線程的ThreadLocal變量,方便必要信息的進一步傳遞。
到此,關于“Inheritable中的ThreadLocal是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。