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
浙公网安备 33010602011771号