从名字上可以看出InheritableThreadLocal就是用来解决父子线程继承时使用的问题,其实大致都可以猜到,我们先来看看例子:
public class InheritableThreadLocalT {
public static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
threadLocal.set("hello");
System.out.println(threadLocal.get());
new Thread() {
@Override
public void run() {
System.out.println(threadLocal.get());
}
}.start();
}
}
再来看看使用另外的
public class InheritableThreadLocalT {
public static final InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
threadLocal.set("hello");
System.out.println(threadLocal.get());
new Thread() {
@Override
public void run() {
System.out.println(threadLocal.get());
new Thread(){
@Override
public void run() {
System.out.println(threadLocal.get());
}
}.start();
}
}.start();
}
}
想必使用方式都一目了然了,就是子线程可访问到父线程里面值,使用也是很简单的,下面我们来看看原理,首先Thread类中有两个map,以及在创建线程时会去关联父线程创建map,会把父线程中的值都拷贝过来,所以如果父线程如果重新set了,对子线程不可见,子线程set了,对父线程也不可见,因为不是同一个map
public class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
......
Thread parent = currentThread();
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
......
}
}
然后我们看下InheritableThreadLocal的实现,这三个方法都是重写父类ThreadLocal的,所以我们最终还是要看看ThreadLocal在相关方法上的实现
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
protected T childValue(T parentValue) {
return parentValue;
}
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}