ThreadLocal在多线程中为每一个线程提供了变量副本,这样子每一个线程都可以在自己的工作空间内使用该副本了。
ThreadLocal的四个常见方法:
public T get()
private T setInitialValue()
public void set(T value)
public void remove()
ThreadLocal使用的数据结构是ThreadLocalMap(本质就是map),首先先看一下ThreadLocalMap的源码:
static class Entry extends WeakReference<ThreadLocal<?>> {
//Entry类是弱引用类型的
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private static final int INITIAL_CAPACITY = 16;//初始容量16
private Entry[] table;
private int size = 0;
private int threshold;
private void setThreshold(int len) {
threshold = len * 2 / 3;//装载因子2/3
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//构造函数
table = new Entry[INITIAL_CAPACITY];//初始一个长度为INITIAL_CAPACITY的表
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);//计算元素存放的位置
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
private ThreadLocalMap(ThreadLocalMap parentMap) {
//私有构造方法
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new Entry[len];
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
Object value = key.childValue(e.value);
Entry c = new Entry(key, value);
int h = key.threadLocalHashCode & (len - 1);
while (table[h] != null)
h = nextIndex(h, len);//用开放定址法 如果有冲突 则寻找下一个
table[h] = c;
size++;
}
}
}
}
看完ThreadLocalMap的源代码,接下来看一下ThreadLocal几个常用方法。
public T get() {
Thread t = Thread.currentThread();//获取当前线程获取key
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();//获取值
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}