ThreadLocal源码探析( 三 )

  • 获取当前线程的ThreadLocalMap对象
  • 从map中根据this(当前的threadlocal对象)获取线程存储的Entry节点 。
  • 从Entry节点获取存储的对应Value副本值返回 。
  • map为空的话返回初始值null , 即线程变量副本为null 。
remove方法清除Map中的KV
/* * Removes the current thread's value for this thread-local * variable.  If this thread-local variable is subsequently * {@linkplain #get read} by the current thread, its value will be * reinitialized by invoking its {@link #initialValue} method, * unless its value is {@linkplain #set set} by the current thread * in the interim.  This may result in multiple invocations of the * <tt>initialValue</tt> method in the current thread. * * @since 1.5 */public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null)     m.remove(this);}ThreadLocalMap getMap(Thread t) {    return t.threadLocals;} /**  * Reove the entry for key.  */    private void remove(ThreadLocal<?> key) {    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)]) {              if (e.get() == key) {                  e.clear();                  expungeStaleEntry(i);                  return;              }          }    }下面再认识一下ThreadLocalMap , 一个真正存储(隔离)数据的东西 。
ThreadLocalMapThreadLocalMap是ThreadLocal的内部类 , 实现了一套自己的Map结构 , 咱们看一下内部的继承关系就一目了然 。
ThreadLocal源码探析

文章插图
 
其Entry使用的是K-V方式来组织数据 , Entry中key是ThreadLocal对象 , 且是一个弱引用(弱引用 , 生命周期只能存活到下次GC前) 。
对于弱引用引发的问题我们最后再说 。
static class Entry extends WeakReference<ThreadLocal<?>> {        /** The value associated with this ThreadLocal. */         Object value;         Entry(ThreadLocal<?> k, Object v) {            super(k);            value = v;        } }ThreadLocalMap的成员变量
static class ThreadLocalMap {    /**     * The initial capacity -- MUST be a power of two.     */    private static final int INITIAL_CAPACITY = 16;    /**     * The table, resized as necessary.     * table.length MUST always be a power of two.     */    private Entry[] table;    /**     * The number of entries in the table.     */    private int size = 0;    /**     * The next size value at which to resize.     */    private int threshold; // Default to 0}


推荐阅读