ThreadLocal源码分析

1.Thread类中有一个叫 threadLocals的变量
 
ThreadLocal.ThreadLocalMap threadLocals = null;
threadLocals 是ThreadLocalMap类型的,ThreadLocalMap 是ThreadLocal的一个内部类。
 
源码中这个变量的注释如下:
/* ThreadLocal values pertaining to this thread. This map is maintained
 * by the ThreadLocal class. */
 大意:与线程相关的ThreadLocal变量,这个map由ThreadLocal类来操作。
 所以在thread类中没有找到改变threadLocals值的地方。只有在exit()方法中对threadLocals置空。
 
2.ThreadLocal.ThreadLocalMap
 
  1.ThreadLocalMap中还有一个内部类
      static class Entry extends WeakReference<ThreadLocal>
    有一个带参的构造函数叫Entry(ThreadLocal k, Object v),
    从参数名字来看,Entry应该是一个弱引用的键值对,key是ThreadLocal的对象
 
  2.ThreadLocal.ThreadLocalMap中有一个entry的数组,作为存储变量的容器
      private Entry[] table;
 
3.ThreadLocal
  1.set方法
    public void set(T value) {
    //获取当前线程
    Thread t = Thread.currentThread();
    //获取当前线程对应的map,return t.threadLocals; getMap直接返回当前线程的threadLocals,之前提过的那个
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //map非空将当前的threadlocal对象作为键,放到map中
        map.set(this, value);
    else
        //map是空的话调用createMap函数创建map
        createMap(t, value);
    }
 
 
  2.getMap函数
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
 
  3.createMap函数
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    //firstKey就是this,当前的这个threadlocal对象,
    ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
    table = new Entry[INITIAL_CAPACITY]; //创建entry数组
    int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
    table[i] = new Entry(firstKey, firstValue);//将kv放入数组中
    size = 1; //初始化数组
    setThreshold(INITIAL_CAPACITY);//初始化数组容量
    }
 
   4.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();
    }
 
  总的来说ThreadLocal变量是这样的,Thread类中有一个ThreadLocalMap类型的map,这个map的entry是以ThreadLocal为key的,
  value是范型可以随意指定。当一个线程定义了很多个ThreadLocal变量他们会存在这个map中,
  所以把一个变量加入到threadlocal中就相当于该变量是线程私有属性,而且在这个线程的任何地方随存随取,所以threadlocal变量
  是线程内全局,所有线程之间局部的。
 
  另外:我们可以看下Entry的构造函数:
    Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
 
  entry的值只不过是v的引用的copy,就是entry的value实际指向的内存跟传进来的v指向的内存是同一个,所以对ThreadLocal的entryvalue操作
  会改变原有的对象,所以加入到ThreadLocal变量并不等于新建了一个该变量的copy。ThreadLocal并不能解决共享变量的问题,所以也不能像很多
  blog中说的解决多线程问题之类的。
原文地址:https://www.cnblogs.com/kniught-ice/p/5461101.html