背景
前几天 在项目中集成hystrix,结果从ThreadLocal中获取不到数据。
原因:
hystrix(默认会使用线程隔离策略) 会隔离线程,提高系统的安全性
解决方案
把 ThreadLocal 换成 InheritableThreadLocal
案例:
public class ThreadLocalTest extends Thread{
static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args){
threadLocal.set("123");
new ThreadLocalTest().start();
}
@Override
public void run() {
System.out.println(threadLocal.get()+"---");
}
}
运行结果:
在main线程中给 ThreaLocal 设置值后,子线程中获取不到变量:
null---
Process finished with exit code 0
解决方案:
public class ThreadLocalTest extends Thread{
static InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args){
threadLocal.set("123");
new ThreadLocalTest().start();
}
@Override
public void run() {
System.out.println(threadLocal.get()+"---");
}
}
123---
Process finished with exit code 0
使用 InheritableThreadLocal 解决了线程隔离获取不到变量的问题, 当然我们不能 知其然而不知道其所以然。那么为什么InheritableThreadLocal 可以在线程隔离的情况下获取到值呢? 让我们走进源代码:
这是 Thread 这段代码会在 Thread 初始化的时候执行, Thread 维护了 inheritableThreadLocals,threadLocals 两个变量 类型都是 ThreadLocalMap ,在下面这段代码中看到 它判断了inheritableThreadLocals 是否为空,不为空就传入 就把parent 的 inheritableThreadLocals 给到 当前线程的 this.inheritableThreadLocals
可以看到 InheritableThreadLocal 重写了getMap,createMap方法,这两方法传入的参数都是Thread, return t.inheritableThreadLocals; 这里其实就是引用到了 上一步 返回到 Thread的inheritableThreadLocals变量
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);
}
}
这样我们就明白了,InheritableThreadLocal为什么能实现Thread的隔离还能获取变量。
评论区