ThreadLocal 被称为“线程内部单例”,它被用来在线程内部进行数据存取,相当于数据绑定到了某一线程,数据的作用域也仅限于当前线程。在任何一线程中访问ThreadLocal,也只是访问当前线程的ThreadLocal。
ThreadLocal内部维护了一个静态的ThreadLocalMap类,而ThreadLocalMap类内部,又维护了一个Entry类及Entry[],我们通过ThreadLocal进行数据的存取操作,最终都是对Entry[]进行存取操作,存取的也就是Entry对象。Entry的构造方法,要传入的也就是:当前线程ThreadLocal引用和要存储的值。
我们 new 一个ThreadLocal对象:
ThreadLocal
mThreadLocal.set("Hello word");
(1)ThreadLocal内部set()方法实现
public voidset(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map !=null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap构造方法之一:
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
table=newEntry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY-1);
table[i] =newEntry(firstKey, firstValue);
size=1;
setThreshold(INITIAL_CAPACITY);
}
首先:获取到当前Thread,然后根据当前线程拿到线程内部的ThreadLocalMap,判断ThreadLocalMap是否null,第一次是为null,然后会调用CreateMap(ThreadLocal,value)new 一个ThreadLocalMap,ThreadLocalMap的构造方法内部,先初始化一个长度为16的Entry[],接着根据ThreadLocal的hashCode值对数组初始长度16取模,获得该数据应在Entry[]中的存储位置,然后把数据存储到数组中。
其次:如果ThreadLocalMap不为null,则会调用ThreadLocalMap的set(ThreadLocal,Value)方法,set(ThreadLocal,Value)方法内部,先根据传入的ThreadLocal的hashCode值对Entry[]长度取模,拿到该数据在Entry[]中应存储的位置,如果该位置上有Entry,则把新的值赋值给它,如果没有,则new一个新的Entry存储到Entry[]中。
(2)ThreadLocal的get()方法内部实现
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map !=null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if(e !=null)
return (T)e.value;
}
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;
}
protected T initialValue() {
return null;
}
首先:获取当前线程,获取当前线程内部的ThreadLocalMap,判断ThreadLocalMap是否null,第一次是为null,然后调用setInitialValue(),setInitialValue()方法内部,先调用initialValue()返回一个null值,接着会调用createMap(TheadLocal,Value)初始化一个ThreadLocalMap,所以第一次获取到ThreadLocal内部的数据是为null的。
其次:如果ThreadLocalMap不为null,就会调用ThreadLocalMap内部的getEntry(),genEntry()先根据传入的ThreadLocal的hashCode值对Entry[]数组长度取模,获得该数据在数组中的位置,然后拿到该数据。