对于ThreadLocal类的一些思考

今天在牛客网上看到有人发面经提到了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类当作一个专属于当前线程的存储变量的工具是可以的。但是在实际应用中的更多作用可能还需要在以后遇到了才会知道。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值