/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ staticclassEntryextendsWeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value;
/** * Returns the value in the current thread's copy of this * thread-local variable. If the variable has no value for the * current thread, it is first initialized to the value returned * by an invocation of the {@link #initialValue} method. * * @return the current thread's value of this thread-local */ public T get() { //获取当前线程 Threadt= Thread.currentThread(); //获取当前线程所关联的一个Map ThreadLocalMapmap= getMap(t); if (map != null) { ThreadLocalMap.Entrye= map.getEntry(this); //找到了已经初始化过的线程本地对象,那么转型后返回即可 if (e != null) { @SuppressWarnings("unchecked") Tresult= (T)e.value; return result; } } //执行到这里说明map为空或者线程本地对象尚未初始化,那么继续初始化逻辑 return setInitialValue(); }
/** * Get the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * * @param t the current thread * @return the map */ ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
/** * Variant of set() to establish initialValue. Used instead * of set() in case user has overridden the set() method. * * @return the initial value */ private T setInitialValue() { //首先调用initialValue来初始化对象 Tvalue= initialValue(); //获取线程对象 Threadt= Thread.currentThread(); //获取线程对象关联的map ThreadLocalMapmap= getMap(t); //如果map已经初始化了 if (map != null) //那么直接将value存入即可,注意以ThreadLocal对象为键值 map.set(this, value); else //初始化map并且存入value createMap(t, value); return value; }
/** * Returns the current thread's "initial value" for this * thread-local variable. This method will be invoked the first * time a thread accesses the variable with the {@link #get} * method, unless the thread previously invoked the {@link #set} * method, in which case the {@code initialValue} method will not * be invoked for the thread. Normally, this method is invoked at * most once per thread, but it may be invoked again in case of * subsequent invocations of {@link #remove} followed by {@link #get}. * * <p>This implementation simply returns {@code null}; if the * programmer desires thread-local variables to have an initial * value other than {@code null}, {@code ThreadLocal} must be * subclassed, and this method overridden. Typically, an * anonymous inner class will be used. * * @return the initial value for this thread-local */ protected T initialValue() { returnnull; }
3.1.4 createMap
就是新建一个Map然后赋值给指定的Thread对象,并且存入一个指定的value,很简单,不多说
1 2 3 4 5 6 7 8 9 10
/** * Create the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the map */ voidcreateMap(Thread t, T firstValue) { t.threadLocals = newThreadLocalMap(this, firstValue); }
/** * Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses will have no need to * override this method, relying solely on the {@link #initialValue} * method to set the values of thread-locals. * * @param value the value to be stored in the current thread's copy of * this thread-local. */ publicvoidset(T value) { //获取当前线程对象 Threadt= Thread.currentThread(); //获取当前线程对象关联的map ThreadLocalMapmap= getMap(t); //如果map已经初始化过了 if (map != null) //直接存入值即可 map.set(this, value); else //否则初始化map并且存入值 createMap(t, value); }
3.3 remove
remove方法用于将当前ThreadLocal为键值的键值对从当前线程的map中除去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/** * 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 * {@code initialValue} method in the current thread. * * @since 1.5 */ publicvoidremove() { ThreadLocalMapm= getMap(Thread.currentThread()); if (m != null) m.remove(this); }