承接上文,这篇次要就剖析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多平台公布
发表回复