Thread.currentThread()与ThreadLocal

-- 最近再探Spring,深入研究了一下Spring的Introduce Advice。其中涉及到了关于ThreadLocal的一些内容,回顾了一下,这里做个记录。

-- Java DOC说ThreadLocal存储了一个线程的局部变量,内部究竟是怎样的。具体如下:

-- Thread中维护了一个ThreadLocal.ThreadLocalMap的变量。
  
ThreadLocal.ThreadLocalMap threadLocals = null;

  
-- 当我们调用ThreadLocal的set方法的时候,实际上是往Thread.currentThread()也就是当前线程的ThreadLocalMap变量中添加数据。
  
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
   


-- 由此可见,一个Thread可以维护多个ThreadLocal

-- 再看ThreadLocal.ThreadLocalMap(ThreadLocalMap是ThreadLocal的静态内部类,为了方便,下面简写为ThreadLocalMap)
   ThreadLocalMap是不是像他名字所写的那样使用了一个Map来储存一个Thread的局部变量呢?答案是否定的。
  
private Entry[] table;

   实际上它用的是一个ThreadLocalMap.Entry数组。这个数组的初始容量为16.
  
private static final int INITIAL_CAPACITY = 16;


-- Entry是ThreadLocalMap静态内部类。下面简写为Entry。

-- 那么又是如何往Entry[ ]中添加数据呢?
   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();
    }


    -- 这里使用了ThreadLocal的threadLocalHashCode与16进制的F做与操作的结果作为索引来向Entry数组添加数据。上面判断是否已经使用当前TheadLocal添加了数据,下面对数组越界做处理。具体怎么处理的,时间所限没有深究。

-- 至于Entry本质上就是一个没有存取器的Java Bean。它有两个属性:
   ThreadLocal类型的key,
   Object类型的Value

你可能感兴趣的:(threadLocal)