版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}
}