关于ThreadLocal的几点误区

关于ThreadLocal的几点误区

我们都知道遇到线程安全问题时可以用ThreadLocal来解决。但是关于这个类,很多人都存在一些误区。
误区一:ThreadLocal就是一个map,key就是线程相关的参数,value就是要存放的数据。
误区二:一个线程对应一个ThreadLocal,重复设置值会被覆盖。

先看一个例子:

public class ThreadLocalTest {
    public static ThreadLocal<String> threadLocalOne = new ThreadLocal<String>();
    public static ThreadLocal<String> threadLocalTwo = new ThreadLocal<String>();
    public static void main(String[] args) {
        threadLocalOne.set("first!");
        threadLocalTwo.set("second!");
        System.out.println(threadLocalOne.get());
        System.out.println(threadLocalTwo.get());
    }
}

运行结果:
first!
second!
说明一个线程其实可以设置多个与当前线程相关的数据,只是要设置多个ThreadLocal,否则如果只在一个ThreadLocal里面重复设置是会被覆盖的。

那么ThreadLocal是不是就仅仅是一个类似map的东西呢?

ThreadLocal的set方法只是把线程id相关的数据作为key放进了map吗?

我们一起来看看它的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);
        }
    }

设置数据的时候其实是把ThreadLocal对象本身作为key放到了一个map里面,注意这里不是线程本身,这个map就是ThreadLocalMap类型的对象,这个ThreadLocalMap是哪里来的呢?
我们看看getMap(t)这个方法是怎么实现的吧:

 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

其实就是从当前线程对象里面的一个字段获取的。
threadLocals是Thread类型的对象里面的一个成员变量,我们在new Thread的时候并不会初始化这个成员变量,它的初始化在ThreadLocal的set方法里面。
createMap(t, value);这个代码就会去初始化这个成员变量:

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
 ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

这个ThreadLocalMap就非常类似我们的HashMap了。

总结起来就是:ThreadLocal的set方法其实就是把自己作为map的key,数据作为value设置到了当前线程对象的成员变量threadLocals里面,而这个threadLocals成员变量其实就是一个非常类似于HashMap的map类型对象,这个对象会在第一次set方法被调用时候初始化。也就是说如果要存放多个与线程相关的对象只需要多new几个ThreadLocal,每个ThreadLocal对应一个数据对象,每个数据对象的key就是各个ThreadLocal本身。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值