ThreadLocal源码解析

在Java并发编程中,合理地使用线程本地变量或线程私有变量,能够一定程度上降低线程与线程之间的耦合,并简化编程的难度。通过继承Thread类并在子类中定义私有属性可以实现线程局部变量或私有变量,但是这样的方式灵活性低,而且必须通过Thread的子类的一些接口实现对定义的线程局部变量或私有变量的的访问。

ThreadLocal提供了一种更加灵活更合理的设置线程本地变量的方式,核心的实现逻辑是:Thread类中定义并持有一个ThreadLocalMap(类似于java.util中的map容器类),在一个Thread的执行流中,通过ThreadLocal类的一个实例的set和get方法可以向该Thread实例持有的ThreadLocalMap实例中添加和获取值。ThreadLocalMap的key是ThreadLocal类的一个对象,对应的value是该ThreadLocal对象的set(T value)方法中的value,ThreadLocalMap的value只要是对象即可。

ThreadLocal<Integer> t_1 = new ThreadLocal<>();
t_1.set(1);
ThreadLocal<Integer> t_2 = new ThreadLocal<>();
t_1.set(2);
System.out.println(t_1.get());  //输出1
System.out.println(t_2.get());  //输出2

 set方法源码:

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t); //获取当前线程对象的ThreadLocalMap
        if (map != null)
            map.set(this, value); //当前线程对象的ThreadLocalMap已经初始化,则将value保存
        else
            createMap(t, value);//当前线程对象的ThreadLocalMap未初始化,则初始化,并将value保存
    }

ThreadLocalMap的set方法源码:

        private void set(ThreadLocal<?> key, Object value) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

在这里key,也就是ThreadLocal的hash值(threadLocalHashCode)的实现是一个比较有意思的地方,查看源码:

public class ThreadLocal<T> {
  
    private final int threadLocalHashCode = nextHashCode();

    private static AtomicInteger nextHashCode =
        new AtomicInteger();

    private static final int HASH_INCREMENT = 0x61c88647;

    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

    .........

}

ThreadLocal 对象的hash值是通过ThreadLocal类的一个static属性 nextHashCode实现的,这个属性是AtomicInteger类型的,且通过nextHashCode()方法获取一个hash值的值的时候,是通过将属性nextHashCode的值加上一个常量 HASH_INCREMENT。

 

参考:http://blog.csdn.net/cainiao_2010/article/details/23255023

 

posted on 2017-10-20 22:12  三个包子  阅读(168)  评论(0)    收藏  举报