ThreadLocal深入淺出

ThreadLocal深入淺出

    一、分析ThreadLocal源碼

    ThreadLocal的核心方法一共就幾個,get(),set()等等,我們由get()開始,一邊分析其源碼,一邊揭開ThreadLocal的面紗。

    先看看JDK7中的get()源碼:

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
    當調用get()方法時,首先會獲取當前線程,然後調用getMap方法獲取一個ThreadLocalMap對象,我們來看看ThreadLocalMap的源碼:
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    很顯然,getMap(Thread t)方法用於返回線程的ThreadLocalMap類型成員變量,我們來看看Thread類源碼:
ThreadLocal.ThreadLocalMap threadLocals = null;
    成員變量是一個初始爲null的值,ThreadLocalMap是ThreadLocal的一個內部靜態類。好了,再回到get()方法,以下代碼說明,當ThreadLocalMap對象及其Entry對象皆不爲空的時候,返回Entry的value,否則,返回setInitialValue()返回值:
if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();

    Entry是一個鍵值對應的關係,維護着ThreadLocal對象和Object對象之間的關係。

    setInitialValue()的源碼如下:

private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

    代碼十分簡單,新建一個value,噹噹前線程ThreadLocalMap成員變量爲空,則創建map,如果不爲空,在map中插入this和value的對應關係,同時返回value。initialValue()是一個protected修飾的方法,用於設置value的默認值,可以重寫。

    至此就夠了,由上文我們可以知道,關鍵概念是ThreadLocalMap對象,爲Thread的成員變量,維護着ThreadLocal對象和Object對象的鍵值對應關係,可見,一個Thread可以和多個ThreadLocal對象對應,他們之間的關係圖如下:




    因爲,ThreadLocal是弱引用,如果一直沒有被引用,勢必會被GC回收,此時,Thread中ThreadLocalMap的Entry的key就爲空,如果Thread遲遲不結束,value對應的對象就一直不會被釋放,造成內存泄露。

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