说 InheritableThreadLocal 之前我们先说下ThreadLocal
什么是ThreadLocal?
可以去看看 : 对ThreadLocal的思考
背景
前几天 在项目中集成hystrix,结果从ThreadLocal中获取不到数据。
原因
hystrix 会隔离线程,提高系统的安全性
解决方案
把 ThreadLocal 换成 InheritableThreadLocal
案例:
1 |
|
运行结果: 子线程中 获取不到 变量1
2
3null---
Process finished with exit code 0
//解决方案1
2
3
4
5
6
7
8
9
10
11
12
13
14public class ThreadLocalTest extends Thread{
static InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args){
threadLocal.set("123");
new ThreadLocalTest().start();
}
public void run() {
System.out.println(threadLocal.get()+"---");
}
}
1 | 123--- |
使用 InheritableThreadLocal 解决了线程隔离获取不到变量的问题,
当然我们不能 知其然而不知道其所以然。
那么为什么InheritableThreadLocal 可以在线程隔离的情况下获取到值呢?
让我们走进源代码:
这是 Thread 的源代码的部分源码大概在418行,这段代码会在 Thread 初始化的时候执行,
Thread 维护了 inheritableThreadLocals,threadLocals 两个变量 类型都是 ThreadLocalMap
,在下面这段代码中看到 它判断了inheritableThreadLocals 是否为空,不为空就传入 createInheritedMap 往下看 createInheritedMap的源码1
2
3
4
5if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
此处生成了一个新增 ThreadLocalMap 返回 然后 赋值给了 Thread的this.inheritableThreadLocals,
流程就是
Thread初始化->创建一个新的ThreadLocalMap(存储了当前线程变量的)返回—->这步 看 InheritableThreadLocal的源码1
2
3static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
可以看到 InheritableThreadLocal 重写了getMap,createMap方法,这两方法传入的参数都是Thread, return t.inheritableThreadLocals; 这里其实就是引用到了 上一步 返回到 Thread的inheritableThreadLocals变量1
2
3
4
5
6
7
8
9
10
11
12
13
14public 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);
}
}
这样我们就明白了,InheritableThreadLocal为什么能实现Thread的隔离还能获取变量。
如果本文对您有帮助,请不要吝啬您的点赞。谢谢!
评论加载中