五、面試必問知識點——ThreadLocal實現、原理、示例

小胖的瘋子發表於2018-11-28

7、ThreadLocal底層實現

   每個Thread都有一個ThreadLocalMap物件,ThreadLocalMap持有物件的引用,
   該物件跟當前執行緒繫結,ThreadLocalMap以當前的threadLocal物件為key,
   以ThreadLocal裡面存的值為value。儲存一份變數的副本,副本儲存線上程中的,
   而不是儲存在ThreadLocal變數中;從而實現執行緒之間的資料的隔離
複製程式碼

8、 ThreadLocal原始碼:

1)、set()方法:
        public void set(T value) {
        //獲取當前執行緒物件
        Thread t = Thread.currentThread();
        //獲取當前執行緒物件的ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null)
            //以當前threadLocal物件為key,實際儲存物件為value
            map.set(this, value);
        else
            createMap(t, value);
        }
        //獲取Thread類中的ThreadLocalMap物件
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
        }
        //建立Thread類中的ThreadLocalMap成員物件
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
        //初始化ThreadLocalMap物件
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            //INITIAL_CAPACITY初始值為16
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
        //初始化載入因子
        private void setThreshold(int len) {
            threshold = len * 2 / 3;
        }

2)、get()方法:
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                //threadlocal例項為key獲取到對應Entry,然後從Entry中取出物件
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            //map為空時,設定初始值
            return setInitialValue();
        }
        
        private T setInitialValue() {
            T value = initialValue();
            //同set方法一樣
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        }
        
        protected T initialValue() {
            return null;
        }
3)、remove()方法:
        public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
        }
複製程式碼

9、ThreadLocal使用場景(JDBC的連線、管理會話HttpSession等)

如圖:

五、面試必問知識點——ThreadLocal實現、原理、示例

相關文章