溫馨提示×

溫馨提示×

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

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

ThreadLocal原理是什么

發布時間:2020-11-06 14:03:33 來源:億速云 閱讀:160 作者:小新 欄目:編程語言

這篇文章主要介紹ThreadLocal原理是什么,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

ThreadLocal即線程局部變量的意思!所以什么是線程局部變量?這玩意有什么鳥用?是不是面試被問到了說不出個一二三?今天就來扒一扒這貨的源碼,從根本上了解這貨是干啥的。

Thread、ThreadLocalMap、Entry三者關系

其實研究下來他的源碼實現,其實也沒想象的那么復雜,其最主要有以下幾點:

1、Java可以通過Thread.currentThread()來獲得當前的Thread的實例對象。既然能拿到這Thread對象實例,那么我們就可以操作該實例(的屬性),比如為該Thread對象設置一個值什么。

2、每一個Thread對象都有一個ThradLocalMap實例,該實例有一個一個Entry組成的數組,Entry對象有兩個主要屬性:value和ThreadLocal的弱引用,其中value這個屬性就是值設置給當前線程所持有,也是ThreadLocal的核心屬性:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

注意Entry繼承自WeakReference,其key就是ThreadLocal對象?。▓D1)

ThreadLocal原理是什么

結合1和2兩個知識點,我們就可以知道我們拿到Thread對象之后,就可以操控當前線程對象的ThreadLocalMap對象,然后把想要保存的value交給ThreadLocalMap的Entry的value屬性,Thread,ThreadLocalMap,value三者之間的關系可以用下圖表示(圖2):

ThreadLocal原理是什么

通過上圖我們可以得出這么一個結論:一個Thread對象持有一個ThreadLocalMap對象,然后呢,一個ThreadLoalMap對象又包含了多個ThreadLlocal對象及ThreadLocal對象所在線程的value?。?!一言以蔽之: 一個Thread對象可以持有多個ThreadLocal對象的變量值value

那么ThreadLocal和Thread又有啥關系呢?二者是怎能對value進行讀取的呢?下面就根據源碼來簡單的分析下。

ThreadLocal和Thread的關聯

先看看ThreadLocal的set方法:

 public void set(T value) {
         //獲取當前線程
        Thread t = Thread.currentThread();
        //獲取當前線程持有的ThreadLocalMap
        ThreadLocal.ThreadLocalMap map = getMap(t);
        //將value設置給threadlocalMap
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

set方法很邏輯很簡單(j結合上圖2看更好理解):

1、通過currentThread方法拿到當前Thread對象

2、獲取當前Thread對象的ThreadLoalMap對象

3、將value連同ThreadLocal對象自己組成一個Entry對象保存在

ThreadLoalMap的Entry類型的數組中。

在來看看ThreadLocal的get方法:

public T get() {
    //獲取當前線程
    Thread t = Thread.currentThread();
    //獲取當前線程的ThreadLocalMap對象
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        //獲取與ThreadLocal對象想關聯的value
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            //獲取值
            T result = (T)e.value;
            return result;
        }
    }
    //為空返回初始化值
    return setInitialValue();
}

可以發展get的整體邏輯也很簡單:

1、獲取當前Thread對象

2、獲取當前Thread對象的ThreadLocalMap對象

3、從ThreadLocalMap中獲取與ThreadLocal相關聯的Entry對象,具體的就是以ThreadLocal為key獲取。

4、獲取步驟3的Entry的value屬性,并返回之。

通過整體觀察get和set方法可以得出如下結論:ThreadLocal對象調用set方法就是往Thread對象的ThreadLocalMap里面添加值;ThreadLocal對象調用get方法就是從Thread對象的ThreadLocalMap里面獲取值。核心就是操縱Thread對象的ThreadLocalMap對象進行value的讀和寫。原理就這么簡單。

那么位于不同線程的不同ThreadLocal對象,在其他線程里保存值是一個什么樣的關系呢?可以通過下圖來清晰的描述出來:

ThreadLocal原理是什么

ThreadLocal的使用實例

我們在知道在Android中一個線程只有一個Looper對象,那么是怎么做到的呢?就是ThreadLocal發揮了作用,看看Looper的prepare方法:

//定義一個靜態的ThreadLocal變量
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 

private static void prepare(boolean quitAllowed) {
        //一個Thread只能關聯一個Looper對象
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

觀察prepare方法可以知道,先通過sThreadLocal的get方法判斷當前線程是否已經擁有了一個Looper對象,如果有就拋出一個異常;如果當前線程還沒有設置Looper對象,則調用ThreadLocal的set方法,初始化一個Looper對象交給當前線程:

sThreadLocal.set(new Looper(quitAllowed));

這樣就確保了一個線程只有一個Looper對象。

到此為止,關于ThreadLocal的原理已經基本分析完畢,至于內部是怎么set和get的,博主并沒有做太細的分析,因為沒必要,了解ThreadLocal的工作原因以及使用場景即可。

以上是ThreadLocal原理是什么的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

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

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女