這篇文章主要介紹“Inheritable中的ThreadLocal是什么”,在日常操作中,相信很多人在Inheritable中的ThreadLocal是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Inheritable中的ThreadLocal是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
瑞安ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話(huà)聯(lián)系或者加微信:028-86922220(備注:SSL證書(shū)合作)期待與您的合作!
1、簡(jiǎn)介 在上一篇 ThreadLocal詳解 中,我們?cè)敿?xì)介紹了ThreadLocal原理及設(shè)計(jì),從源碼層面上分析了ThreadLocal。但由于ThreadLocal設(shè)計(jì)之初就是為了綁定當(dāng)前線(xiàn)程,如果希望當(dāng)前線(xiàn)程的ThreadLocal能夠被子線(xiàn)程使用,實(shí)現(xiàn)方式就會(huì)相當(dāng)困難(需要用戶(hù)自己在代碼中傳遞)。在此背景下,InheritableThreadLocal應(yīng)運(yùn)而生。
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、應(yīng)用 調(diào)用鏈追蹤:在調(diào)用鏈系統(tǒng)設(shè)計(jì)中,為了優(yōu)化系統(tǒng)運(yùn)行速度,會(huì)使用多線(xiàn)程編程,為了保證調(diào)用鏈ID能夠自然的在多線(xiàn)程間傳遞,需要考慮ThreadLocal傳遞問(wèn)題(大多數(shù)系統(tǒng)會(huì)使用線(xiàn)程池技術(shù),這已經(jīng)不僅僅是InheritableThreadLocal能夠解決的了,我會(huì)在另外一篇文章中介紹相關(guān)技術(shù)實(shí)現(xiàn))。
3、InheritableThreadLocal類(lèi) InheritableThreadLocal類(lèi)重寫(xiě)了ThreadLocal的3個(gè)函數(shù):
`/** * 該函數(shù)在父線(xiàn)程創(chuàng)建子線(xiàn)程,向子線(xiàn)程復(fù)制InheritableThreadLocal變量時(shí)使用 */ protected T childValue(T parentValue) { return parentValue; } /** * 由于重寫(xiě)了getMap,操作InheritableThreadLocal時(shí), * 將只影響Thread類(lèi)中的inheritableThreadLocals變量, * 與threadLocals變量不再有關(guān)系 */ ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * 類(lèi)似于getMap,操作InheritableThreadLocal時(shí), * 將只影響Thread類(lèi)中的inheritableThreadLocals變量, * 與threadLocals變量不再有關(guān)系 */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); }`
注意:由于重寫(xiě)了getMap()和createMap()兩個(gè)函數(shù),所以當(dāng)
4、線(xiàn)程間傳值實(shí)現(xiàn)原理 說(shuō)到InheritableThreadLocal,還要從Thread類(lèi)說(shuō)起:
public class Thread implements Runnable { ......(其他源碼) /* * 當(dāng)前線(xiàn)程的ThreadLocalMap,主要存儲(chǔ)該線(xiàn)程自身的ThreadLocal */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal,自父線(xiàn)程集成而來(lái)的ThreadLocalMap, * 主要用于父子線(xiàn)程間ThreadLocal變量的傳遞 * 本文主要討論的就是這個(gè)ThreadLocalMap */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ......(其他源碼)
}`
Thread類(lèi)中包含 threadLocals 和 inheritableThreadLocals 兩個(gè)變量,其中 inheritableThreadLocals 即主要存儲(chǔ)可自動(dòng)向子線(xiàn)程中傳遞的ThreadLocal.ThreadLocalMap。 接下來(lái)看一下父線(xiàn)程創(chuàng)建子線(xiàn)程的流程,我們從最簡(jiǎn)單的方式說(shuō)起:
4.1、用戶(hù)創(chuàng)建Thread, Thread thread = new Thread();
4.2、Thread創(chuàng)建
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
4.3、Thread初始化
/** * 默認(rèn)情況下,設(shè)置inheritThreadLocals可傳遞 */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } /** * 初始化一個(gè)線(xiàn)程. * 此函數(shù)有兩處調(diào)用, * 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); ......(其他代碼) }`
可以看到,采用默認(rèn)方式產(chǎn)生子線(xiàn)程時(shí),inheritThreadLocals=true;若此時(shí)父線(xiàn)程inheritableThreadLocals不為空,則將父線(xiàn)程inheritableThreadLocals傳遞至子線(xiàn)程。
4.4、ThreadLocal.createInheritedMap 讓我們繼續(xù)追蹤createInheritedMap:
`static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } /** * 構(gòu)建一個(gè)包含所有parentMap中Inheritable ThreadLocals的ThreadLocalMap * 該函數(shù)只被 createInheritedMap() 調(diào)用. */ private ThreadLocalMap(ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); // ThreadLocalMap 使用 Entry[] table 存儲(chǔ)ThreadLocal table = new Entry[len]; // 逐一復(fù)制 parentMap 的記錄 for (int j = 0; j < len; j++) { Entry e = parentTable[j]; if (e != null) { @SuppressWarnings("unchecked") ThreadLocal
從ThreadLocalMap可知,子線(xiàn)程將parentMap中的所有記錄逐一復(fù)制至自身線(xiàn)程。
5、總結(jié) InheritableThreadLocal主要用于子線(xiàn)程創(chuàng)建時(shí),需要自動(dòng)繼承父線(xiàn)程的ThreadLocal變量,方便必要信息的進(jìn)一步傳遞。
到此,關(guān)于“Inheritable中的ThreadLocal是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!