https://www.cnblogs.com/hama1993/p/10400265.html
ThreadLocal<String> threadLocal=new ThreadLocal();
InheritableThreadLocal<String> inheritableThreadLocal=new InheritableThreadLocal<>();
threadLocal.set("father threadLocal");
inheritableThreadLocal.set("father inheritableThreadLocal");
Thread thread= new Thread(()->{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//子线程通过TL对象在自己的TLMap中没有找到相关的对象:输出null
System.out.println("子线程获取父类threadLocal数据:"+threadLocal.get());
System.out.println("子线程获取父类inheritableThreadLocal数据:"+inheritableThreadLocal.get());
});
inheritableThreadLocal.set("father inheritableThreadLocal is change");
thread.start();
子线程获取父类threadLocal数据:null
子线程获取父类inheritableThreadLocal数据:father inheritableThreadLocal
// TL的set方法,如果是子类的实现,那么获取(getMap)和初始化赋值(createMap)都是ITL对象里的方法
// 其余操作不变(因为hash计算、查找、扩容都是TLMap里需要做的,这里子类ITL只起到一个为Thread对象里哪个TLMap属性赋值的作用)
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// ITL里getMap方法的实现
ThreadLocal.ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals; //返回的其实是Thread对象的inheritableThreadLocals属性
}
// ITL里createMap方法的实现
void createMap(Thread t, T firstValue) {
// 也是给Thread的inheritableThreadLocals属性赋值
t.inheritableThreadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
}
// 初始化一个Thread对象时的代码段(Thread类的init方法)
Thread parent = currentThread();
if (parent.inheritableThreadLocals != null){ //可以看到,如果父线程存在inheritableThreadLocals的时候,会赋值给子线程(当前正在被初始化的线程)
// 利用父线程的TLMap对象,初始化一个TLMap,赋值给自己的inheritableThreadLocals(这就意味着这个TLMap里的值会一直被传递下去)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}
// 看下TL里对应的方法
static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap) {
return new ThreadLocal.ThreadLocalMap(parentMap); //这里就开始初始化TLMap对象了
}
// 根据parentMap来进行初始化子线程的TLMap对象
private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap) {
ThreadLocal.ThreadLocalMap.Entry[] parentTable = parentMap.table; //拿到父线程里的哈希表
int len = parentTable.length;
setThreshold(len); // 设置阈值(具体方法参考上一篇)
table = new ThreadLocal.ThreadLocalMap.Entry[len];
for (int j = 0; j < len; j++) {
ThreadLocal.ThreadLocalMap.Entry e = parentTable[j]; //将父线程里的Entry取出
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get(); //获取key
if (key != null) {
Object value = key.childValue(e.value); //获取value
ThreadLocal.ThreadLocalMap.Entry c = new ThreadLocal.ThreadLocalMap.Entry(key, value); //根据k-v重新生成一个Entry
int h = key.threadLocalHashCode & (len - 1); //计算哈希值
while (table[h] != null)
h = nextIndex(h, len); //线性探查解决哈希冲突问题(具体方法参考上一篇)
table[h] = c; //找到合适的位置后进行赋值
size++;
}
}
}
}
// ITL里的childValue的实现
protected T childValue(T parentValue) {
return parentValue; //直接将父线程里的值返回
}
线程安全问题
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。