承接上文,这篇次要就剖析FastThreadLocal
顺带剖析下相干内容
what
既然又了ThreadLocal
为什么Netty又创立了一个FastThreadLocal
呢,首先,先看下FastThreadLocal
的正文,类正文下面阐明了。简述一下
- 通过
FastThreadLocalThread
拜访会更快 - 取代了Hash映射,应用常量
解决频繁拜访的场景
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多平台公布