ThreadLocal源碼解析

目錄

set(T value)源碼:

get()源碼:

remove()源碼:

總結 


 

前面講Jdbc連接時涉及到ThreadLocal的內容由於要解釋的東西太多,所以另開一篇解釋

ThreadLocal裏面的幾個方法

1、set(T value) 設置ThreadLocal中當前線程共享變量的值。

2、get() 獲取ThreadLocal中當前線程共享變量的值。

3、remove()移除ThreadLocal中當前線程共享變量的值

set(T value)源碼:

public void set(T value) {
//獲取當前線程
        Thread t = Thread.currentThread();
//在ThreadLocal 中,以t來獲取當前線程的一個ThreadLocalMap
        ThreadLocalMap map = getMap(t);
//如果ThreadLocal中有這個map,就把當前類和對應的值傳進去
        if (map != null)
            map.set(this, value);
//如果沒有這個map,就新建一個t線程的ThreadLocalMap,並將value值傳進去
        else
            createMap(t, value);
    }

//在創建t線程的ThreadLocalMap時,同樣要把當前類作爲Key值傳入此ThreadLocalMap中
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

 

get()源碼:

public T get() {
//獲取當前線程
        Thread t = Thread.currentThread();
//獲取當前線程的map
        ThreadLocalMap map = getMap(t);
//判斷當前線程的map是否存在,不爲空
        if (map != null) {
//如果存在,就獲取當前對象的Entry鍵值對
            ThreadLocalMap.Entry e = map.getEntry(this);
//判斷這個鍵值對是否爲空
            if (e != null) {
//如果不是空,就返回對應的value值
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
//此處是當前線程的map不存在,返回setInitialValue,進程初始化
        return setInitialValue();
    }

private T setInitialValue() {
//調用initialValue方法,此方法是初始化ThreadLocal的方法,
        T value = initialValue();
//下面一段代碼是再次判斷ThreadLocal中是否有當前線程的map
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
//根據初始化的內容,決定是在map中插入值,還是新建map插入值
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
//初始化ThreadLocal的方法,一般會在創建ThreadLocal對象時重寫該方法,確保初始化時,不至於爲null
protected T initialValue() {
        return null;
    }

remove()源碼:

public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

移除當前線程的map

PS

1、ThreadLocalMap 是ThreadLocal裏面的一個內部類,相當於Map,是個雙列集合,但是是以(T t,ThreadLocalMap())的形式存儲數據的,ThreadLocalMap()是內部類ThreadLocalMap內的構造方法。

2、爲了防止內存溢出,在每條線程任務執行完後,要調用remove方法溢出ThreadLocal中的連接

3、ThreadLocalMap是根據線性探測的方法來插入數據的。所謂線性探測,就是根據初始key的hashcode值確定元素在table數組中的位置,如果發現這個位置上已經有其他key值的元素被佔用,則利用固定的算法尋找一定步長的下個位置,依次判斷,直至找到能夠存放的位置。ThreadLocalMap解決Hash衝突的方法就是利用步長加1或者減1,來尋找下一個相鄰的位置,直至找到合適的位置

4、因爲ThreadLocalMap處理hash衝突的複雜性,爲了提高性能,建議每個線程只存放一個變量。樣的話所有的線程存放到map中的Key都是相同的ThreadLocal,如果一個線程要保存多個變量,就需要創建多個ThreadLocal,多個ThreadLocal放入Map中時會極大的增加Hash衝突的可能。

tips:下面將我讀到的一篇關於ThreadLocal寫的不錯的文章連接附上,方便查閱。

ThreadLocal深度解析

總結 

 ThreadLocal通過給不同的線程分配各自特有的map,來區分不同的線程,並在每個map中存入以當前對象爲key,存儲數據爲value的Entry鍵值對來區分不同線程的任務,確保,當前線程只能處理當前線程的數據,不能處理其他線程的數據。

能力尚淺,有待進步,如有不足,不吝賜教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章