• 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中说的解决多线程问题之类的。
  • 相关阅读:
    Go语言的流程控制(条件,选择,控制,跳转,闭包)
    Go语言的map
    数据库-关系模型
    数据库的格式化模型(层次模型和网状模型)
    数据库-数据模型
    操作系统的功能与定义
    操作系统功能和定义
    操作系统应用程序
    密码学概论
    JAVA多线程提高四:多个线程之间共享数据的方式
  • 原文地址:https://www.cnblogs.com/kniught-ice/p/5461101.html
Copyright © 2020-2023  润新知