承接上文,这篇次要就剖析FastThreadLocal顺带剖析下相干内容

what

既然又了ThreadLocal为什么Netty又创立了一个FastThreadLocal呢,首先,先看下FastThreadLocal的正文,类正文下面阐明了。简述一下

  1. 通过FastThreadLocalThread拜访会更快
  2. 取代了Hash映射,应用常量
  3. 解决频繁拜访的场景

    A special variant of  ThreadLocal that yields higher access performance when accessed from a FastThreadLocalThread.ThreadLocal的一种非凡变体,当从FastThreadLocalThread进行拜访时,会产生更高的拜访性能。 Internally, a  FastThreadLocal uses a constant index in an array, instead of using hash code and hash table, to look for a variable.  Although seemingly very subtle, it yields slight performance advantage over using a hash  table, and it is useful when accessed frequently. 在外部,FastThreadLocal应用数组中的常量索引,而不是应用哈希代码和哈希表来查找变量。尽管看起来很奥妙,但它比应用哈希表产生了轻微的性能劣势,并且在频繁拜访时十分有用。 To take advantage of this thread-local variable, your thread must be a FastThreadLocalThread or its subtype.By default, all threads created by DefaultThreadFactory are  FastThreadLocalThread due to this reason. 要利用此线程局部变量,你的线程必须是FastThreadLocalThread或其子类型。因为这个起因,默认状况下,DefaultThreadFactory创立的所有线程都是FastThreadLocalThread。 Note that the fast path is only possible on threads that extend  FastThreadLocalThread, because it requires a special field to store the necessary state.  An access by any other kind of thread falls back to a regular link ThreadLocal. 请留神,疾速门路仅实用于扩大FastThreadLocalThread的线程,因为它须要一个非凡字段来存储必要的状态。任何其余类型的线程的拜访都会回退到惯例链接ThreadLocal。

Detail

简述

上一篇看过了,这里就很容易了,也是将存储对象放入到线程中,这里对象就简略粗犷了,没有通过Entry了,而是间接通过Object[]数组,那么是怎么定位的呢,它是通过private static final AtomicInteger nextIndex = new AtomicInteger();来实现的,每次FastThreadLocal创立都会取得惟一的值,自增,防止了哈希碰撞。

初始化会全副设置成一个Object这样就能够晓得FastThreadLocal第一次塞值的中央了,第一次塞值会塞入到variablesToRemoveIndex这个地位,这个地位比拟特地,放的全是FastThreadLocal,当线程执行结束的时候,会比拟不便的革除援用。

先记住一个大略,上面会有具体的剖析,这里呢先记住个大略,上面会一一剖析的

set

    public final void set(V value) {        if (value != InternalThreadLocalMap.UNSET) {            //1.1            InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();            //1.2            setKnownNotUnset(threadLocalMap, value);        } else {            remove();        }    }        //1.1 InternalThreadLocalMap    public static InternalThreadLocalMap get() {        Thread thread = Thread.currentThread();        if (thread instanceof FastThreadLocalThread) {            //2.1            return fastGet((FastThreadLocalThread) thread);        } else {            return slowGet();        }    }        //2.1    private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {        //同样是存储在FastThreadLocalThread中        InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();        //如果没有回创立一个        if (threadLocalMap == null) {            //3.1            thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());        }        return threadLocalMap;    }        //3.1    private InternalThreadLocalMap() {        indexedVariables = newIndexedVariableTable();    }    private static Object[] newIndexedVariableTable() {        //INDEXED_VARIABLE_TABLE_INITIAL_SIZE:32        Object[] array = new Object[INDEXED_VARIABLE_TABLE_INITIAL_SIZE];        //public static final Object UNSET = new Object();        Arrays.fill(array, UNSET);        return array;    }        //1.2    private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {        //2.2         if (threadLocalMap.setIndexedVariable(index, value)) {            //3.2            addToVariablesToRemove(threadLocalMap, this);        }    }        //2.2    public boolean setIndexedVariable(int index, Object value) {        //初始化创立的的Object[]数组,初始化的时候全是UNSET        Object[] lookup = indexedVariables;        //这个index是FastThreadLocal初始化的时候创立的时候就会赋值的,这个前面再剖析        //这里阐明不须要扩容        if (index < lookup.length) {            //老值            Object oldValue = lookup[index];            //设置新值            lookup[index] = value;            //比对老值是否等于UNSET            return oldValue == UNSET;        } else {            //4.1 扩容            expandIndexedVariableTableAndSet(index, value);            return true;        }    }        //3.2    private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {        //private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex();        //返回threadLocalMap,variablesToRemoveIndex地位的值        Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);        Set<FastThreadLocal<?>> variablesToRemove;        if (v == InternalThreadLocalMap.UNSET || v == null) {                        variablesToRemove = Collections.newSetFromMap(new IdentityHashMap<FastThreadLocal<?>, Boolean>());            //往threadLocalMap[variablesToRemoveIndex],设置一个Set            threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove);        } else {            //获取该set            variablesToRemove = (Set<FastThreadLocal<?>>) v;        }        //将以后ThreadLocal增加进该set        variablesToRemove.add(variable);    }    

扩容

它一大串或就是保障最高位开始前面全都为1,+1后就是2的倍数,

而后扩容,把index塞到它应该在的地位上

    private void expandIndexedVariableTableAndSet(int index, Object value) {        Object[] oldArray = indexedVariables;        final int oldCapacity = oldArray.length;        int newCapacity = index;        newCapacity |= newCapacity >>>  1;        newCapacity |= newCapacity >>>  2;        newCapacity |= newCapacity >>>  4;        newCapacity |= newCapacity >>>  8;        newCapacity |= newCapacity >>> 16;        newCapacity ++;        Object[] newArray = Arrays.copyOf(oldArray, newCapacity);        Arrays.fill(newArray, oldCapacity, newArray.length, UNSET);        newArray[index] = value;        indexedVariables = newArray;    }

初始化

上面这边是2个初始化变量,index,每次创立的时候,会顺次递增,variablesToRemoveIndex就是所有FastThreadLocal专用啦。

public class FastThreadLocal<V> {                private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex();        private final int index;    public FastThreadLocal() {        index = InternalThreadLocalMap.nextVariableIndex();    }}  public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {    private static final AtomicInteger nextIndex = new AtomicInteger();    public static int nextVariableIndex() {        int index = nextIndex.getAndIncrement();        if (index < 0) {            nextIndex.decrementAndGet();            throw new IllegalStateException("too many thread-local indexed variables");        }        return index;    }}    

销毁

这里次要看一下variablesToRemoveIndex的用法了,能够参考FastThreadLocalRunnable在执行完结后会调用removeAll革除援用

final class FastThreadLocalRunnable implements Runnable {    private final Runnable runnable;    private FastThreadLocalRunnable(Runnable runnable) {        this.runnable = ObjectUtil.checkNotNull(runnable, "runnable");    }    @Override    public void run() {        try {            runnable.run();        } finally {            FastThreadLocal.removeAll();        }    }}    
    public static void removeAll() {        InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();        if (threadLocalMap == null) {            return;        }        try {            Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);            if (v != null && v != InternalThreadLocalMap.UNSET) {                @SuppressWarnings("unchecked")                //FastThreadLocal汇合                Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;                                FastThreadLocal<?>[] variablesToRemoveArray =                        variablesToRemove.toArray(new FastThreadLocal[0]);                //遍历所有的FastThreadLocal                    for (FastThreadLocal<?> tlv: variablesToRemoveArray) {                    //                    tlv.remove(threadLocalMap);                }            }        } finally {            InternalThreadLocalMap.remove();        }    }        public final void remove(InternalThreadLocalMap threadLocalMap) {        if (threadLocalMap == null) {            return;        }        //1.1        Object v = threadLocalMap.removeIndexedVariable(index);        //1.2        removeFromVariablesToRemove(threadLocalMap, this);        //没有删除的状况        if (v != InternalThreadLocalMap.UNSET) {            try {                //预留模板办法,自定义实现                onRemoval((V) v);            } catch (Exception e) {                PlatformDependent.throwException(e);            }        }    }    //1.1 去援用,赋值为UNSET    public Object removeIndexedVariable(int index) {        Object[] lookup = indexedVariables;        if (index < lookup.length) {            Object v = lookup[index];            lookup[index] = UNSET;            return v;        } else {            return UNSET;        }    }        //1.2    private static void removeFromVariablesToRemove(            InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {        Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);        if (v == InternalThreadLocalMap.UNSET || v == null) {            return;        }        @SuppressWarnings("unchecked")        Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;        //set中去掉这个FastThreadLocal        variablesToRemove.remove(variable);    }

get

这个没啥好说的,一看就懂了

        public final V get() {        InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();        Object v = threadLocalMap.indexedVariable(index);        if (v != InternalThreadLocalMap.UNSET) {            return (V) v;        }        return initialize(threadLocalMap);    }        private V initialize(InternalThreadLocalMap threadLocalMap) {        V v = null;        try {            //模板,自定义实现            v = initialValue();        } catch (Exception e) {            PlatformDependent.throwException(e);        }        threadLocalMap.setIndexedVariable(index, v);        addToVariablesToRemove(threadLocalMap, this);        return v;    }

总结

FastThreadLocal次要外围我感觉就是通过index来取代哈希运算了,然而这样可能带来一个小问题,别频繁创立,why就不剖析了,正文写的很分明了,就是为了速度,over~~

本文由mdnice多平台公布