今天在牛客网上看到有人发面经提到了ThreadLocal类,然后最近做一个大作业也用到了该类,但是只是当作了一个专属于本线程的存储来用,并没有思考他的线程隔离作用的含义,仅仅和我讲线程隔离的话我感觉这个概念有些抽象,所以今天就去继续学习了一下ThreadLocal类。
首先讲一下ThreadLocal类的set方法吧,先看下源码:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
再解释一下
进入到Thread Local的set方法之后,首先会获取当前的CurrentThread,即当前线程对象,然后根据当前线程对象得到一个ThreadLocalMap对象,这个ThreadLocalMap类是ThreadLocal类的一个静态内部类。接着将一对k-v值放入ThreadLocalMap,其中k是当前线程对象,v是set方法的参数。这样的话就将要绑定的变量(set方法的参数)绑定到当前线程了。
之后要取出该绑定的变量的话就可以使用get方法取出,同样get方法内部在从ThreadLocalMap中取出变量的时候,传参也是this,即该函数的调用者,即当前线程对象。这样就确保了只能在当前线程中实现对ThreadLcoal绑定的数据的存取,在别的线程中就无法对该数据进行操作。
但是我看到这边,感觉对线程隔离的含义还是不是很明白,我之前看到有人将ThreadLocal和synchronized相比较,所以我认为他们两个有类似的功能,于是我想了一想,能否让两个线程中的同一个ThreadLocal实例绑定同一个对象呢。
private static ThreadLocal<Object> myThreadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
Dog dog = new Dog("大强","吃饭",2);
myThreadLocal.set(dog);
Object value = myThreadLocal.get();
System.out.println("主线程之中的值:" + value);
// 创建并启动新线程
Thread thread = new Thread(() -> {
// 获取变量值
try {
Object threadValue = myThreadLocal.get();
System.out.println("子线程之中的值:" + threadValue);
} catch (Exception e) {
System.out.println("发现一个异常:" + e);
}
// 修改变量值
myThreadLocal.set(dog);
dog.setName("这是新的名字");
// 获取修改后的变量值
Object updatedValue = myThreadLocal.get();
System.out.println("更新之后的子线程之中的值:" + updatedValue);
// 清理变量
myThreadLocal.remove();
});
thread.start();
Thread.sleep(50); //让主线程休息50ms,让子线程先执行
dog.setAction("这是新的动作");
Object o = myThreadLocal.get();
System.out.println("在主线程中再次更新之后得到的值"+o);
}
我做了以上尝试,我将Dog类的一个实例绑定到了两个线程中,发现该dog实例是可以在两个线程中实现数据共享的具体结果如下:
主线程之中的值:Dog{name='大强', action='吃饭', age=2}
子线程之中的值:null
更新之后的子线程之中的值:Dog{name='这是新的名字', action='吃饭', age=2}
在主线程中再次更新之后得到的值Dog{name='这是新的名字', action='这是新的动作', age=2}
其实也很好理解,其实就是在ThreadLocalMap中存放了两对k-v,其中v都是该Dog实例,k则分别是两个线程对象。
其实理解到这里,我感觉我对源码的解读已经足够了。但是对线程隔离的概念的理解感觉还是一知半解。我现在感觉就是ThreadLoacl类当作一个专属于当前线程的存储变量的工具是可以的。但是在实际应用中的更多作用可能还需要在以后遇到了才会知道。