ThreadLocal的源碼解析

涉及到類:Thread、ThreadLocal、ThreadLocalMap(ThreadLocal的內部類)

含義:這些變量與普通變量不同,每個訪問一個線程(通過其get或set方法)的線程都有其自己的,獨立初始化的變量副本。 ThreadLocal實例通常是希望將狀態與線程關聯的類中的私有靜態字段(例如,用戶ID或交易ID)

例子:

private static class ThreadA extends Thread {
        @Override
        public void run() {

            //  每個訪問一個線程(通過其get或set方法)的線程都有其自己的,獨立初始化的變量副本
            ThreadLocal<Integer> threadlocal = new ThreadLocal<Integer>();
            threadlocal.set(1);

            threadlocal.get();
        }
    }

源碼解析如下:(每一個Thread維護着一個ThreadLocalMap)

class Thread{   
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; // 用於繼承
}

當ThreadLocal的set方法

class ThreadLocal{   
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        // 如果THreadLocalMap爲空,就新建一個
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
}
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals; // 獲得當前線程維護的ThreadLocalMap
    }
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

ThreadLocalMap的key是對應的ThreadLocal<>

class ThreadLocal{  
   public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        // 如果沒有ThreadLocalMap的初始值 
        return setInitialValue();
    }
}

與線程生命狀態相關的體現

class Thread{
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        /* Aggressively null out all reference fields: see bug 4006245 */
        target = null;
        /* Speed the release of some of these resources */
        threadLocals = null;  // 退出時銷燬
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }
}

ThreadLocal使用場景:

(1)使用實例:Handler、looper

class Looper{   
    
    // 獲得每個線程獨立的looper 
    private ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
 
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        // 新建looper其中維護着queue管理Messege,用於線程的通信
        sThreadLocal.set(new Looper(quitAllowed));
    }

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
}

(2)可用於靜態方法在多線程中的調用,獲得專屬當前的線程的內存區域(變量),這個是靜態變量無法實現,因爲靜態變量無法區分線程(Lopper實現方式一致)

public class Text {

    private final static ThreadLocal<Integer> local = new ThreadLocal<Integer>(){
        protected Integer initialValue() {
            return 1;
        }
    };

    public static int A() {
        
        // 每一個線程都會有獨立的一份變量
        Integer integer = local.get();
        local.set(++integer);
        return integer;
    }
}

 

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