ThreadLocal是一个线程独立存储类,通过他的get和set方法,在不同的线程中,可以独立地存取不同的value。每次回顾
Looper源码的时候,都会忘了ThreadLocal是如何实现和工作的,故这次记录下来。
工作原理图

ThreadLocal中的ThreadLocalMap

首先观察ThreadLocal的结构,有两个静态内部类,其中第二个ThreadLocalMap是他工作原理的最重要的类。
此时点开Thread类源码:
/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;
会发现Thread引用了一个ThreadLocal.ThreadLocalMap,并且命名为threadLocals。并且这个引用在每一个Thread对象中只有一个。这样的设计使得每个Thread对象都有一个自己的Map。
Entry extends WeakRefernce
再回到ThreadLocalMap中。
如果看过HashMap或者LinkedHashMap源码应该会对这个Entry的设计很熟悉。代码为:
static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}//...private Entry[] table;//Entry数组//set方法private void set(ThreadLocal<?> key, Object value) {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)]) {ThreadLocal<?> k = e.get();if (k == key) {e.value = value;return;}if (k == null) {replaceStaleEntry(key, value, i);return;}}tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)rehash();}//get方法private Entry getEntry(ThreadLocal<?> key) {int i = key.threadLocalHashCode & (table.length - 1);Entry e = table[i];if (e != null && e.get() == key)return e;elsereturn getEntryAfterMiss(key, i, e);}}
与HashMap不同的是,
- 他继承了
WeakRefernce,key必须是ThreadLocal,value是Object,即任意类型,并且在构造函数中将key传入作为弱引用构造函数的参数。 Entry并没有引用一个next之类的指针,因此无法构成HashMap那样的链表。- 纯粹的是维护一个
Entry数组。 
继承WeakReferenc是因为:ThreadLocal作为key,如果是强引用,会一直被这个ThreadLocalMap引用,而只要后者对应的线程没有结束,那么就算在别处因为不需要了,而将该ThreadLoacal释放(=null),由于在map中的强引用,ThreadLocal对象也无法回收。
因此这里只要设计成弱引用,在别处释放后,垃圾收集器就可以顺利回收ThreadLocal对象。
ThreadLocal
ThreadLocal对象实质上是做为一个key,在不同的线程中的map里,存取不同的对象。
public ThreadLocal() {//...public T get() {Thread t = Thread.currentThread();//获取当前线程ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);//当前对象作为key去getEntry(this)if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}public void set(T value) {Thread t = Thread.currentThread();//获取当前线程ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);//当前对象作为key去set(this,value)elsecreateMap(t, value);}}
剩下的就是一些实现细节了,直接到源码里面去看就行了,主要还是看看顶部的工作原理图,理解原理就行。
