中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Inheritable中的ThreadLocal是什么

發布時間:2021-06-22 14:24:03 來源:億速云 閱讀:121 作者:chen 欄目:大數據

這篇文章主要介紹“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是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长武县| 五台县| 盐津县| 潮安县| 玉树县| 三台县| 太和县| 长宁区| 林周县| 大名县| 桂林市| 维西| 宁明县| 和田市| 台安县| 龙山县| 汉沽区| 六安市| 马山县| 柏乡县| 金溪县| 佛山市| 甘谷县| 沙田区| 鸡西市| 舟山市| 太湖县| 曲沃县| 苗栗市| 文昌市| 宁陵县| 绍兴市| 和静县| 黄平县| 安义县| 黔西| 乐至县| 玉树县| 望奎县| 雅江县| 偏关县|