Netty源码分析---FastThreadLocal

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Pengjx2014/article/details/82914469

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;
    }
}

猜你喜欢

转载自blog.csdn.net/Pengjx2014/article/details/82914469