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;
}
}