ThreadLocal与FastThreadLocal区别
ThreadLocal:
FastThreadLocal:
ThreadLocal和FastThreadLocal 在上图中结果几乎是差不多的,区别主要如下:
1.ThreadLocal的通过key计算Hash值找到对应的Entry,找到value
.对此不清楚可查看源码分析-ThreadLocal
2.而FastThreadLocal则是维护了一个Index,直接就通过这个Index找到对应的value.这就是FastThreadLocal为什么能比ThreadLocal快的主要原因
FastThreadLocal源码
1.首先要了解一个类,FastThreadLocalThread里面有一个InternalThreadLocalMap
public class FastThreadLocalThread extends Thread {
private InternalThreadLocalMap threadLocalMap;
}
2.看看FasThreadLocal的部分源码 (主要是set方法相关)
public class FastThreadLocal<V> {
//3.维护index,这个index代表着当前FastThreadLocal对象在InternalThreadLocalMap的indexedVariables的位置
private final int index;
public FastThreadLocal() {
//4.nextVariableIndex()方法就是AtomicInteger.getAndIncrement(),相当于一个自增Id
//所以每次new一个FastThreadLocal,就可以得到一个属于当前对象的Id
index = InternalThreadLocalMap.nextVariableIndex();
}
public final void set(V value) {
//Object UNSET = new Object(); ///InternalThreadLocalMap.UNSET是一个对象,用来填充未设置值的位置
// 即InternalThreadLocalMap初始化后,里面的成员变量 Object[] indexedVariables 会全部用 InternalThreadLocalMap.UNSET
//这个对象先填充,代表着未设置值。
if (value != InternalThreadLocalMap.UNSET) {
//1.获取当前线程的InternalThreadLocalMap
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
setKnownNotUnset(threadLocalMap, value);
} else {
remove();
}
private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {
//2.直接就通过Index,将值设置进去,这里就是与逻辑上与ThreadLocal最主要的区别
if (threadLocalMap.setIndexedVariable(index, value)) {
addToVariablesToRemove(threadLocalMap, this);
}
}
}
}
3. InternalThreadLocalMap.get()部分源码如下
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {
public static InternalThreadLocalMap get() {
Thread thread = Thread.currentThread();
//当前线程为FastThreadLocalThread才可以调用fastGet, 用得不对性能反而比不上ThreadLocal的原因
if (thread instanceof FastThreadLocalThread) {
return fastGet((FastThreadLocalThread) thread);
} else {
return slowGet();
}
}
private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {
InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();
if (threadLocalMap == null) {
thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());
}
return threadLocalMap;
}
private static InternalThreadLocalMap slowGet() {
ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap;
InternalThreadLocalMap ret = slowThreadLocalMap.get();
if (ret == null) {
ret = new InternalThreadLocalMap();
slowThreadLocalMap.set(ret);
}
return ret;
}
}
4.看看FasThreadLocal的get方法
public final V get() {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
//直接就通过index获取值
Object v = threadLocalMap.indexedVariable(index);
if (v != InternalThreadLocalMap.UNSET) {
//已经设置值, 直接返回
return (V) v;
}
//未设置值,返回一个null
return initialize(threadLocalMap);
}
public Object indexedVariable(int index) {
Object[] lookup = indexedVariables;
return index < lookup.length? lookup[index] : UNSET;
}
5.InternalThreadLocalMap indexedVariables 填充 UNSET,代表着未设置值。
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {
private InternalThreadLocalMap() {
super(newIndexedVariableTable());
}
private static Object[] newIndexedVariableTable() {
Object[] array = new Object[INDEXED_VARIABLE_TABLE_INITIAL_SIZE];
Arrays.fill(array, UNSET);
return array;
}
}
6.想发挥FastThreadLocal的性能优势,线程一定要用FastThreadLocalThread
public class FastThreadLocalTest {
static FastThreadLocal<Integer> fastThreadLocal1 = new FastThreadLocal<>();
static FastThreadLocal<Integer> fastThreadLocal2 = new FastThreadLocal<>();
public static void main(String[] args) {
FastThreadLocalThread threadA = new FastThreadLocalThread(new Runnable() {
@Override
public void run() {
fastThreadLocal1.set(1);
fastThreadLocal2.set(2);
}
});
FastThreadLocalThread threadB = new FastThreadLocalThread(new Runnable() {
@Override
public void run() {
fastThreadLocal1.set(3);
fastThreadLocal2.set(4);
}
});
}
}