ThreadLocal原理及使用场景大揭秘( 三 )

看了set方法 , get方法就
/**     * Returns the value in the current thread's copy of this     * thread-local variable.  If the variable has no value for the     * current thread, it is first initialized to the value returned     * by an invocation of the {@link #initialValue} method.     *     * @return the current thread's value of this thread-local*/public T get() {  Thread t = Thread.currentThread();  ThreadLocalMap map = getMap(t);  if (map != null) {       ThreadLocalMap.Entry e = map.getEntry(this);        if (e != null) {            @SuppressWarnings("unchecked")             T result = (T)e.value;              return result;            }        }    return setInitialValue();}/**     * Variant of set() to establish initialValue. Used instead     * of set() in case user has overridden the set() method.     *     * @return the initial value  */private T setInitialValue() {   T value = initialValue();//null   Thread t = Thread.currentThread();   ThreadLocalMap map = getMap(t);   if (map != null)        map.set(this, value);   else       createMap(t, value);        return value; }//默认值nullprotected T initialValue() {  return null;}源码总结:总体来讲 , ThreadLocal源码比较好理解 。ThreadLocalMap虽然在ThreadLocal中定义 , 但是被Thread.threadLocals引用 。这样保证了一个Thread拥有独立的ThreadLocalMap , 做到和其他线程隔离 。而ThreadLocalMap的key就是ThreadLocal实例 , value就是线程变量 。
再看一下最开始的源码 。
public static void main(String[] args) {        ThreadLocal<String> a =new ThreadLocal<String>();        a.set("1");        a.set("2");        System.out.println(a.get());    }//输出结果是2 。貌似“1”被覆盖了 。//确实是被覆盖了 , Thread.threadLocals的key是a , 值当然只能有一个 , get到的值也是最后一个value//单线程的内部实现类似这样   ThreadLocal<String> a =new ThreadLocal<String>();   Map map = new HashMap();   map.put(a,"1");   map.put(a,"2");   System.out.println(map.get(a));源码中的问题总结

  1. ThreadLocalMap的hash冲突问题
上文说到ThreadLocalMap解决hash冲突的方法是开放地址 。但对threadLocalHashCode没有详细说明 , 下面补充说明一下它 。
//计算数组下标int i = key.threadLocalHashCode & (len-1);private final int threadLocalHashCode = nextHashCode();/*** The next hash code to be given out. Updated atomically. Starts at* zero.* 线程安全的原子类 , 发出下一个hash code*/private static AtomicInteger nextHashCode = new AtomicInteger();/*** getAndAdd(v)返回的结果是nextHashCode , 但是nextHashCode+=HASH_INCREMENT;*/private static int nextHashCode() {  return nextHashCode.getAndAdd(HASH_INCREMENT);}/*** The difference between successively generated hash codes - turns* implicit sequential thread-local IDs into near-optimally spread* multiplicative hash values for power-of-two-sized tables.* 自增量*/private static final int HASH_INCREMENT = 0x61c88647;


推荐阅读