ThreadLocal内部原理解析

2017-03-25  本文已影响0人  Jacksimo

        ThreadLocal 被称为“线程内部单例”,它被用来在线程内部进行数据存取,相当于数据绑定到了某一线程,数据的作用域也仅限于当前线程。在任何一线程中访问ThreadLocal,也只是访问当前线程的ThreadLocal。

ThreadLocal内部维护了一个静态的ThreadLocalMap类,而ThreadLocalMap类内部,又维护了一个Entry类及Entry[],我们通过ThreadLocal进行数据的存取操作,最终都是对Entry[]进行存取操作,存取的也就是Entry对象。Entry的构造方法,要传入的也就是:当前线程ThreadLocal引用和要存储的值。

我们 new 一个ThreadLocal对象:

ThreadLocal<String> mThreadLocal=newThreadLocal<String>();

mThreadLocal.set("Hello word");

(1)ThreadLocal内部set()方法实现

public voidset(T value) {

       Thread t = Thread.currentThread();

       ThreadLocalMap map = getMap(t);

        if(map !=null)

               map.set(this, value);

        else

               createMap(t, value);

}

ThreadLocalMap构造方法之一:

ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {

           table=newEntry[INITIAL_CAPACITY];

           int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY-1);

           table[i] =newEntry(firstKey, firstValue);

           size=1;

           setThreshold(INITIAL_CAPACITY);

}

首先:获取到当前Thread,然后根据当前线程拿到线程内部的ThreadLocalMap,判断ThreadLocalMap是否null,第一次是为null,然后会调用CreateMap(ThreadLocal,value)new 一个ThreadLocalMap,ThreadLocalMap的构造方法内部,先初始化一个长度为16的Entry[],接着根据ThreadLocal的hashCode值对数组初始长度16取模,获得该数据应在Entry[]中的存储位置,然后把数据存储到数组中。

其次:如果ThreadLocalMap不为null,则会调用ThreadLocalMap的set(ThreadLocal,Value)方法,set(ThreadLocal,Value)方法内部,先根据传入的ThreadLocal的hashCode值对Entry[]长度取模,拿到该数据在Entry[]中应存储的位置,如果该位置上有Entry,则把新的值赋值给它,如果没有,则new一个新的Entry存储到Entry[]中。

(2)ThreadLocal的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();

}

private T setInitialValue() {

      T  value = initialValue();

      Thread t = Thread.currentThread();

      ThreadLocalMap map = getMap(t);

      if(map !=null)

              map.set(this, value);

     else

            createMap(t, value);

      return value;

}

protected T initialValue() {

return null;

}

首先:获取当前线程,获取当前线程内部的ThreadLocalMap,判断ThreadLocalMap是否null,第一次是为null,然后调用setInitialValue(),setInitialValue()方法内部,先调用initialValue()返回一个null值,接着会调用createMap(TheadLocal,Value)初始化一个ThreadLocalMap,所以第一次获取到ThreadLocal内部的数据是为null的。

其次:如果ThreadLocalMap不为null,就会调用ThreadLocalMap内部的getEntry(),genEntry()先根据传入的ThreadLocal的hashCode值对Entry[]数组长度取模,获得该数据在数组中的位置,然后拿到该数据。

上一篇下一篇

猜你喜欢

热点阅读