一、常见用法
ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。
二、翻阅代码
以get方法为例,get中获取的值是从当前线程(Thread.currentThread())中获取的,我们查看get方法中使用的getMap()发现,其实他是将Thread中的变量threadlocals中的值取出来的。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //这里使用到了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();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals; // 这里看出其实threadLocals为Thread的一个变量
}
然而,这个threadLocals存的是什么呢?存储结构又是什么呢?
void createMap(Thread t, T firstValue) {
// 这里我们可以看出,其结构 map(ThreadLocal,Object)
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
我们对threadLocals赋值发生的时间,即调用createMap的时间是
private T setInitialValue() {
T value = initialValue(); //这个方法返回的值,其实是null。
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value); //存在map即Thread的threadLocals不为空这set
else
createMap(t, value); //如果为null,创建新的ThreadLocalMap进行set赋值给
return value; //threadLocals
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //这里和get方法相似
if (map != null) //下面和初始化的逻辑相同
map.set(this, value);
else
createMap(t, value);
}
从而得出的结论是:
Thread中包含threadlocals即ThreadLocal中使用的ThreadLocalMap,同时ThreadLocalMap中的存储格式是这样的ThreadLocalMap<ThreadLocal,Object>.。
所以get方法获取当前ThreadLocal时中的变量,首先获取当前线程,从当前线程中获取threadlocals即ThreadLocal中使用的ThreadLocalMap。然后,从ThreadLocalMap中获取当前ThreadLocal的变量值。
可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。其实上面的的过程即访问副本的过程。
以上不理解的更详细的介绍可以参考:http://www.cnblogs.com/dolphin0520/p/3920407.html