Netty源碼分析---FastThreadLocal

FastThreadLocal實現原理

 FastThreadLocal是JDK中ThreadLocal的擴充,通過對重建FastThreadLocal的線程建立索引的方式來存儲線程本地變量。get set值的過程中根據整形索引index實現線程本地變量的快速訪問。通過index索引訪問線程本地變量具有比ThreadLocal通過ThreadLocalMap訪問線程變量更快的效率。
 Thread中的ThreadLocalMap存儲ThreadLocalThreadLocalMap內部使用ThreadLocalMap.Entry數組存儲每一個ThreadLocal,存儲計算和HashMap類似,要計算key的索引位置=key.threadLocalHashCode&(len-1),中間可能需要計算衝突,使用的是線程探測方法(當前索引在被佔用下,使用下一個索引)。達到一定條件後,還需擴充數組長度,rehash,效率不是太高。另外,還需要使用者注意內存泄漏問題。

FastThreadLocal源碼分析

 FastThreadLocal實現如下:

public class FastThreadLocal<V> extends ThreadLocal<V> {
    static final Object EMPTY = new Object();
    //下一個線程的索引值
    private static final AtomicInteger NEXT_INDEX = new AtomicInteger(0);
    //當前線程的索引值
    private final int index;
    //如果創建的FastThreadLocal的線程不是FastThreadLocalThread,初始值值存儲ThreadLocal
    private final ThreadLocal<V> fallback = new ThreadLocal<V>() {
        @Override
        protected V initialValue() {
            return FastThreadLocal.this.initialValue();
        }
    };
    //創建FastThreadLocal
    public FastThreadLocal() {
        index = NEXT_INDEX.getAndIncrement();
        if (index < 0) {
            NEXT_INDEX.decrementAndGet();
            throw new IllegalStateException("Maximal number (" + Integer.MAX_VALUE + ") of FastThreadLocal exceeded");
        }
    }

    /**
     * 爲當前線程村值
     */
    @Override
    public void set(V value) {
        //獲取當前創建FastThreadLocal的線程
        Thread thread = Thread.currentThread();
        //如果創建的FastThreadLocal的線程不是FastThreadLocalThread,值存儲ThreadLocal
        if (!(thread instanceof FastThreadLocalThread)) {
            fallback.set(value);
            return;
        }
        FastThreadLocalThread fastThread = (FastThreadLocalThread) thread;
        Object[] lookup = fastThread.lookup;
        //如果存儲值的數組越界,執行擴容
        if (index >= lookup.length) {
            lookup = fastThread.expandArray(index);
        }
        // 值存儲
        lookup[index] = value;
    }

    /**
     * 刪除不需要存儲的值
     */
    @Override
    public void remove() {
        Thread thread = Thread.currentThread();
        if (!(thread instanceof FastThreadLocalThread)) {
            fallback.remove();
            return;
        }
        Object[] lookup = ((FastThreadLocalThread) thread).lookup;
        if (index >= lookup.length) {
            return;
        }
        lookup[index] = EMPTY;
    }

    /**
     * 返回當前線程存儲的值,執行過程是,如果獲取值的線程不是FastThreadLocalThread
     * 從ThreadLocal中獲取值,否則根據index從數組lookup中獲取值
     */
    @Override
    @SuppressWarnings("unchecked")
    public V get() {
        Thread thread = Thread.currentThread();
        if (!(thread instanceof FastThreadLocalThread)) {
            return fallback.get();
        }
        FastThreadLocalThread fastThread = (FastThreadLocalThread) thread;

        Object[] lookup = fastThread.lookup;
        Object v;
        if (index >= lookup.length) {
            v = initialValue();
            lookup = fastThread.expandArray(index);
            lookup[index] = v;
        } else {
            v = lookup[index];
            if (v == EMPTY) {
                v = initialValue();
                lookup[index] = v;
            }
        }
        return (V) v;
    }
}

FastThreadLocalThread

 創建FastThreadLocal的FastThreadLocalThread實現如下:

public class FastThreadLocalThread extends Thread {
   //存儲FastThreadLocal中的值的數組,
    Object[] lookup = newArray();
     ....
     //數組初始化
    private static Object[] newArray() {
        Object[] array = new Object[32];
        Arrays.fill(array, FastThreadLocal.EMPTY);
        return array;
    }

   //數組擴容,每次擴大2倍
    Object[] expandArray(int length) {
        int newCapacity = lookup.length;
        do {
            // double capacity until it is big enough
            newCapacity <<= 1;

            if (newCapacity < 0) {
                throw new IllegalStateException();
            }

        } while (length > newCapacity);
       //填充值
        Object[] array = new Object[newCapacity];
        System.arraycopy(lookup, 0, array, 0, lookup.length);
        Arrays.fill(array, lookup.length, array.length, FastThreadLocal.EMPTY);
        lookup = array;
        return lookup;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章