FastThreadLocal,看名字就可以知道,netty君让其优化了。我们先来看看ThreadLocal哪里慢了需要fast,上一篇分析我们知道,Thread内有一个ThreadLocalMap的成员,该成员相当于一个map(数组+线性扫描),该map以ThreadLocal为key,若要定位到相应的value,需要两步。先是根据ThreadLocal的hashCode取余定位到数组的小标,因为是线性扫描,所以很有可能当前不是,需要往后遍历直到找到。而netty,使用一定的机制使其无需第二步操作。
因为ThreadLocal里面没有相应的接口,netty只能自己实现FastThreadLocalThread继承Thread在里面设有自己的ThreadLocalMap。
public class FastThreadLocalThread extends Thread {
// This will be set to true if we have a chance to wrap the Runnable.
private final boolean cleanupFastThreadLocals;
private InternalThreadLocalMap threadLocalMap;
其中cleanupFastThreadLocals从注释中可以读出当封装runnable时候该值为true。
private InternalThreadLocalMap() {
super(newIndexedVariableTable());
}
private static Object[] newIndexedVariableTable() {
Object[] array = new Object[32];
Arrays.fill(array, UNSET);
return array;
}
从InternalThreadLocalMap的构造可以看到,InternalThreadLocalMap也采用了数组形式存储。
UnpaddedInternalThreadLocalMap(Object[] indexedVariables) {
this.indexedVariables = indexedVariables;
}
我们再看看其父类UnpaddedInternalThreadLocalMap的成员
static final ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = new ThreadLocal<InternalThreadLocalMap>();
static final AtomicInteger nextIndex = new AtomicInteger();
/** Used by {@link FastThreadLocal} */
Object[] indexedVariables;
// Core thread-locals
int futureListenerStackDepth;
int localChannelReaderStackDepth;
Map<Class<?>, Boolean> handlerSharableCache;
IntegerHolder counterHashCode;
ThreadLocalRandom random;
Map<Class<?>, TypeParameterMatcher> typeParameterMatcherGetCache;
Map<Class<?>, Map<String, TypeParameterMatcher>> typeParameterMatcherFindCache;
// String-related thread-locals
StringBuilder stringBuilder;
Map<Charset, CharsetEncoder> charsetEncoderCache;