ThreadLocal中有四个常用方法:initalValuesetgetremoveinitalValue先看initalValue,这个方法有两个调整方法覆写initalValue/***Returnsitthecurrentthread-value's"inthis".此方法将在线程第一次使用{@link#get}*方法访问变量时被调用,除非线程先前调用了{@link#set}*方法,在这种情况下,{@codeinitialValue}方法*不会为线程调用。通常,此方法每个线程最多调用一次,但在随后调用{@link#remove}和{@link#get}的情况下,它可能会再次调用。**
此实现仅返回{@codenull};如果*程序员希望线程局部变量的初始值不是{@codenull},则{@codeThreadLocal}必须是*子类,并且重写此方法。通常,一个*匿名内部类将被使用。**@return这个局部线程的初始值*/protectedTinitialValue(){returnnull;注意这个方法在第一次调用get的时候会触发withInitial/***创建一个线程局部变量。变量的初始值是*通过调用{@codeSupplier}上的{@codeget}方法确定的。**@param线程本地值的类型*@paramsupplier用于确定初始值的供应商*@return一个新的线程局部变量*@throwsNullPointerException如果指定的供应商为空*@since1.8*/publicstaticThreadLocalwithInitial(Suppliersupplier){returnnewSuppliedThreadLocal<>(supplier);调用withInitial需要传入一个实现了Supplier。其实它需要一个get方法来返回需要持有的对象。再看get方法/***返回这个线程局部变量的当前线程副本中的值。如果变量对于当前线程没有值,它首先被初始化为返回的值*通过调用{@link#initialValue}方法。**@return这个线程局部的当前线程的值*/publicTget(){Threadt=Thread.currentThread();//获取当前线程ThreadLocalMapmap=getMap(t);//当前线程为key,获取hashMap中对应的ThreadLocalMapif(map!=null){//如果存在,则获取值ThreadLocalMap.Entrye=map.getEntry(this);if(e!=null){//如果值存在,转换类型并返回@SuppressWarnings("unchecked")Tresult=(T)e.value;返回结果;}}返回setInitialValue();//如果映射不存在,则初始化它}注释说,返回当前线程在本地线程变量中的副本。如果当前线程无法获取该变量,则调用initialValue方法并返回该方法的返回值。查看getMap(t)及其相关方法/***获取与ThreadLocal关联的地图。在*InheritableThreadLocal中重写。**@paramt当前线程*@return映射*/ThreadLocalMapgetMap(Threadt){returnt.threadLocals;}/***创建与ThreadLocal关联的映射。在*InheritableThreadLocal中重写。**@paramt当前线程*@paramfirstValue映射初始条目的值*/voidcreateMap(Threadt,TfirstValue){t.threadLocals=newThreadLocalMap(this,firstValue);}/*ThreadLocal值属于这个线程。该映射由ThreadLocal类维护*。*/ThreadLocal.ThreadLocalMapthreadLocals=null;getMap:获取与AThreadLocal相关的地图。createMap:创建ThreadLoacl相关的map,入参为newThreadLocalMap(this,firstValue),this为当前ThreadLocal对象;由此我们可以知道,一个thread线程对应一个threadLoacl对象,一个threadLoacl对象对应一个map。threadLocals与当前线程关联的ThreadLocal值。set/***将此线程局部变量的当前线程副本设置为指定值。大多数子类不需要*重写此方法,仅依赖{@link#initialValue}*方法来设置线程局部变量的值。**@paramvalue要存储在当前线程的副本中的值*这个线程局部的。*/publicvoidset(Tvalue){Threadt=Thread.currentThread();//获取当前线程线程ThreadLocalMapmap=getMap(t);//获取mapif(map!=null)map.set(this,value);//设置值elsecreateMap(t,value);//初始化映射}remove/***删除当前线程的这个线程本地变量的值。如果这个线程局部变量随后被当前线程{@linkplain#getread},它的值将通过调用它的{@link#initialValue}方法重新初始化,*除非它的值是{@linkplain#setset}经过当前线程*在此期间。这可能会导致在当前线程中多次调用*{@codeinitialValue}方法。**@since1.5*/publicvoidremove(){ThreadLocalMapm=getMap(Thread.currentThread());//获取地图if(m!=null)m.remove(this);//删除map中对应的Threadlocal对象及其对应的值,这是当前调用该方法的threadlocal对象}