涉及到三个实体类
- ThreadLocal
- Thread
- ThreadLocalMap
//ThreadLocalMap是ThreadLocal的内部类
ThreadLocalMap{
//类似于HashMap,键值分别是ThreadLocal、对应的值
Entry<ThreadLocal, Object>[] entry;
}
Thread{
//保存了线程私有的ThreadLocalMap
ThreadLocalMap map;
}
ThreadLocal{
//获取被哪个线程调用的
Thread t = Thread.currentThread();
//获取当前线程在该ThreadLocal下的
get(){
//获取该线程的ThreadLocalMap
map_temp = t.map;
//如果map_temp为空,则根据自己重写的初始化策略进行初始化,并存入对应的ThreadLocalMap中对应的槽中
if(map_temp == null){
initVal = init();
map_temp.set(this, initVal);
}
//类似于HashMap根据键查找值,这里的键是ThreadLocal对象本身
return map_temp.get(this);
}
}
可继承的InheritableThreadLocal
public class Test {
private static final ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
//父线程
new Thread(()->{
inheritableThreadLocal.set("hzw");
//子线程
new Thread(()->{
System.out.println(inheritableThreadLocal.get());
}).start();
}).start();
}
}
运行结果是打印出hzw
准确来说是复制父线程的数据,当父线程remove掉后,子线程还可以获取到,示例如下
public class Test {
private static final ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
new Thread(()->{
inheritableThreadLocal.set("hzw");
new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(inheritableThreadLocal.get());
}).start();
inheritableThreadLocal.remove();
System.out.println("属性移除");
}).start();
}
}
运行结果是hzw,说明父线程移除后,子线程仍保留
源码解析:4个主要阶段
public class Test {
private static final ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
//父线程
new Thread(()->{ ..........................................1
inheritableThreadLocal.set("hzw"); ....................2
//子线程
new Thread(()->{ ......................................3
System.out.println(inheritableThreadLocal.get()); .4
}).start();
}).start();
}
}
1.创建父线程(第1行对应的代码)
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
上述代码是Thread初始化时执行的,由于父线程的父线程是main,main中还没进行ThreadLocal操作,所以parent.inheritableThreadLocals==null,上述if逻辑内代码不执行
2.父线程存储值(第2行对应的代码)
InheritableThreadLocal没有重写set方法,所以set方法在ThreadLocal中调用,紧接着set方法中调用了createMap方法,此方法被重写,所以执行以下代码:
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
父子类createMap的唯一区别:ThreadLocal中创建的Map存储在t.threadLocals中,而InheritableThreadLocal中的createMap方法存储在t.inheritableThreadLocals中。
3.子线程初始化(第3行对应的代码)
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
第二步后,父线程的inheritableThreadLocals不为空,上述代码的if逻辑会执行,传入父线程的inheritedMap,为当前线程即子线程创建InheritedMap,并赋值给inheritableThreadLocals。具体创建过程如下:
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++;
}
}
}
}
其实就是将父线程的map复制给子线程,所以父线程map移除后,子线程会保留
4.子线程取值(第4行对应的代码)
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); .......................1
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
调用的是ThreadLocal中的get,我们主要关心ThreadLocalMap map = getMap(t);这一行。这个和createMap一样被重写了,子类和父类实现逻辑是分别返回threadLocals和interitableThreadLocals,相当于set和get方法。