请说一下ThreadLocal的原理?
-
从
Thread
类源代码入手。public class Thread implements Runnable { ...... //与此线程有关的ThreadLocal值。由ThreadLocal类维护 ThreadLocal.ThreadLocalMap threadLocals = null; //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ...... }
从上面
Thread
类 源代码可以看出Thread
类中有一个threadLocals
和 一个inheritableThreadLocals
变量,它们都是ThreadLocalMap
类型的变量,我们可以把ThreadLocalMap
理解为ThreadLocal
类实现的定制化的HashMap
。默认情况下这两个变量都是null,只有当前线程调用ThreadLocal
类的set
或get
方法时才创建它们,实际上调用这两个方法的时候,我们调用的是ThreadLocalMap
类对应的get()
、set()
方法。ThreadLocal
类的set()
方法public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
通过上面这些内容,我们足以通过猜测得出结论:最终的变量是放在了当前线程的
ThreadLocalMap
中,并不是存在ThreadLocal
上,ThreadLocal 可以理解为只是ThreadLocalMap的封装,传递了变量值。每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为key的键值对。 比如我们在同一个线程中声明了两个
ThreadLocal
对象的话,会使用Thread
内部都是使用仅有那个ThreadLocalMap
存放数据的,ThreadLocalMap
的 key 就是ThreadLocal
对象,value 就是ThreadLocal
对象调用set
方法设置的值。ThreadLocal
是 map结构是为了让每个线程可以关联多个ThreadLocal
变量。这也就解释了ThreadLocal声明的变量为什么在每一个线程都有自己的专属本地变量。public class Thread implements Runnable { ...... //与此线程有关的ThreadLocal值。由ThreadLocal类维护 ThreadLocal.ThreadLocalMap threadLocals = null; //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ...... }
ThreadLocalMap
是ThreadLocal
的静态内部类。