ThreadLocal源码解析

这个类提供了线程变量,这不同于其他的变量,它能在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的。

使用示例:

public static void main(String[] args) {
        ThreadLocal<String> str = new ThreadLocal<String>();
        str.set("hello word");
        System.out.println(str.get());
    }

接下来我们来看看ThreadLocal的源码。

protected T initialValue() {
        return null;
    }

类中的protected方法,一般用于我们给Thread变量赋初始值。

其中有个静态内部类ThreadLocalMap,其中的数据结构如下

static class Entry extends WeakReference<ThreadLocal> {

            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

此map的key中ThreadLocal为一个弱引用。当ThreadLocal没有强引用时,此key就会变成null被垃圾回收。注意此时value还在,有可能引起内存泄露。只有当调用get或set方法时才能移除。

每个Thread中有这样一个变量

ThreadLocal.ThreadLocalMap threadLocals = null;

当第一次调用set方法时,会将 threadLocals 赋值

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

看下createMap方法,会创建ThreadLocalMap,并赋值给线程

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);
        }

其中Entry的下标是通过神奇的0x61c88647数,使得均匀分布在2的n次方的数组上。
再来看下ThreadLocal的get方法。

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();
    }

已当前线程为key取得ThreadLocalMap ,然后在根据Threadlocal实例取得对应的值并返回。
~~~~~~~~~~
ThreadLocal实现时为什么把Map定义在Thread对象里存成Map
而不是定义在ThreadLocal里存成Map

第一种方式在set的时候这么写
Map map = Thread.currentThread().threadLocalMap;
map.put(this,obj);
第二种方式这么写
threadLocalMap.put(Thread.currentThread(),obj);

第二种是多个线程共享一个map,必须处理同步,性能不如第一个高

其他参考

http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/
http://www.cnblogs.com/ilellen/p/4135266.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久梦歌行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值