并发编程之ThreadLocal<T>(六)

前言:

ThreadLocal<T>为每个线程提供一个独立的空间,用于存储每个线程自己的变量,多线程并发访问不会出现竞争等并发问题。内部用到了自定义的ThreadLocalMap,但是key值是线程对应的ThreadLocal对象而不是线程本身。ThreadLocal的本质是让每个线程都持有一个key为该ThreadLocal对象的Map。这样每次在get或者set的时候直接取线程的该Map通过该ThreadLocal对象(key)对其进行get或者set操作即可。再往深处挖就会发现Map本质上是一个Entry数组,而Entry持有的key实际上是ThreadLocal对象的弱引用,在ThreadLocal对象的引用变为null时ThreadLocal对象可能被垃圾回收掉,而此时弱引用也会变为null。我们常用的private static声明的ThreadLocal一般不会被垃圾回收,因此Map可以一直持有该对象。

1、ThreadLocal重要成员

//ThreadLocal本身作为Map的key的hash值,用于存放数据的时候对key的均匀分布
private final int threadLocalHashCode = nextHashCode();
//下一个hash值
private static AtomicInteger nextHashCode =
        new AtomicInteger();
//计算下一个hash值的增量
private static final int HASH_INCREMENT = 0x61c88647;
//这是ThreadLocal能存储数据的基础
static class ThreadLocalMap

ThreadLocal的成员变量不多,其中最重要的就是静态内部类ThreadLocalMap了,剩下计算hash值的两个变量我们后续用到的时候再说,这里先留个钩子。

2、ThreadLocal的重要方法
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

get/set方法是我们最常用的方法,方法实现也很简单,取当前线程-->取当前线程关联的Map-->调用Map的put/get/remove方法。着重分析里面的getMap和createMap方法。

//获取Map拿到的是当前线程相关联的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}
ThreadLocal.ThreadLocalMap threadLocals = null;
//创建的Map是内部类ThreadLocalMap
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
}

这里创建的Map是ThreadLocalMap,其中的Key是ThreadLocal对象本身而不是线程,value是你调用set方法设置的value。
分析到这可以发现问题的关键在于ThreadLocalMap这个内部类:

3、ThreadLocalMap:
3.1、成员变量
//用来存储数据的最小单元,本质上是一个弱引用,在垃圾回收的时候如果对ThreadLocal的引用都是弱引用那么回收该对象
static class Entry extends WeakReference<ThreadLocal> {
            Object value;
            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
        }
  }
//初始容量,必须是2的次方数
private static final int INITIAL_CAPACITY = 16;
//Entry桶,长度为2的倍数
private Entry[] table;
//桶中Entry的个数
priva
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值