介绍ThreadLocal的官方API是这样解释的:“这个类提供了线程局部(thread-local)变量。这些变量不同于普通的对应变量,因为访问一个变量(通过它的get或set方法)有自己的局部变量,独立于变量的初始化副本。ThreadLocal实例通常是类中的私有静态字段,希望将状态与某个线程(例如,用户ID或事务ID)关联起来。”大致有两个意思:ThreadLocal提供了一种访问变量的特殊方式:访问的变量属于当前线程,即保证每个线程的变量是不同的,同一个线程可以在任何地方获取该变量是一致的,这就是所谓的线程隔离。如果要使用ThreadLocal,通常定义为私有静态类型。在我看来,最好将其定义为私有静态最终类型。应用场景ThreadLocal通常用于共享数据。当要在多个方法中使用一个变量时,这个变量就是当前线程的状态,其他线程不依赖于这个变量。首先想到的是在方法内部定义变量,然后在方法之间传递参数使用,这种方法可以解决问题,但是有一个烦人的地方就是每个方法都需要声明形参,多次声明,和多次通话。影响代码的美观和维护。有没有办法访问像私有静态这样的变量?这可以在课堂上的任何地方使用。这时候ThreadLocal就大显身手了。实践我们先来看一段代码:mportjava.util.HashMap;导入java.util.Map;publicclassTreadLocalTest{//staticThreadLocalthreadLocal=newThreadLocal(){//@Override//protectedHashMapinitialValue(){//System.out.println(Thread.currentThread().getName()+”initialValue”);//returnnewHashMap();////};publicstaticclassT1implementsRunnable{privatefinalstaticMapmap=newHashMap();intid;publicT1(intid){this.id=id;}publicvoidrun(){//Mapmap=threadLocal.get();for(inti=0;i<20;i++){map.put(i,i+id*100);try{Thread.sleep(100);}catch(Exceptionex){}}System.out.println(Thread.currentThread().getName()+"#map.size()="+map.size()+"#"+map);}}publicstaticvoidmain(String[]args){Thread[]runs=newThread[15];T1t=newT1(1);for(inti=0;i=threshold)rehash();}这个的主要函数方法就是说说KEY-VALUE是保存在ThreadLocalMap中的,这里至少我们看到KEY其实就是key.threadLocalHashCode,而ThreadLocalMap也维护了Entry数组,我们会在下一节讲解。这里涉及到Hash冲突的处理,不会像HashMap那样出现冲突。它将以链表的形式添加。如果对这个Hash冲突的解决方案感兴趣,可以进一步研究源码。由于ThreadLocalMap也是使用Entry来存储对象,所以我们看一下Entry类的声明。ThreadLocalMap内部定义了Entry:staticclassEntryextendsWeakReference{/**ThevalueassociatedwiththisThreadLocal.*/Objectvalue;Entry(ThreadLocalk,Objectv){super(k);value=v;}}这里我们看到Entry集成了WeakReference类,而泛型声明了ThreadLocal,即每个Entry对象都保留了对ThreadLocal实例的弱引用。这样做的原因是线程在结束后,需要将ThreadLocal实例从map中移除,以回收内存空间。总结首先,ThreadLocalMap并不是为了解决线程安全的问题,而是提供一种机制将实例绑定到当前线程,类似于隔离的作用。事实上,方法中的新变量也可以达到类似的效果。ThreadLocalMap与线程安全无关。它绑定的实例不是多个线程共享的,而是每个线程一个新的。这个实例绝对不是共享的。如果是共享的,会造成线程安全问题。ThreadLocalMap的目的是将实例变量共享为全局变量,可以在程序的任何方法中访问。网上很多人说ThreadLocalMap解决了线程安全的问题。其实顾名思义,两者不是一类问题。