在分析 ThreadLocal 方法的时,我们了解到 ThreadLocal 的操作实际上是围绕 ThreadLocalMap 展开的。所以,我们有必要分析一下 ThreadLocalMap 的源码。
ThreadLocalMap 是 ThreadLocal 的内部类,没有实现 Map 接口,它是用独立的方式实现 Map 的功能,其内部的 Entry 也是独立实现。
该结构图对于源码如下。
static class ThreadLocalMap { /** * 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. */ static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } }
/** * 初始容器 -- 必须是 2 的整次方 */ private static final int INITIAL_CAPACITY = 16; /** * 存放数据的 table, 必要时会扩容. * 数组的长度必须是 2 的整次方. */ private Entry[] table; /** * 数组里面 entry 的个数,可以判断 table 当前使用量是否超过阀值 */ private int size = 0; /** * 进行扩容的阀值,表使用量大于它的时候进行扩容 */ private int threshold; // 默认为 0
和 HashMap 类似,INITIAL_CAPACITY 代码这个 Map 的初始容量,table 是一个 Entry 类型的数组,用于存储数据,size 代表表中存储数目;threadhold 代表需要扩容时对应 size 的阀值。
/** * Entry 继承 WeakReference, 并且用 ThreadLocal 作为 key * 如果 key 为 null,意味着 key 不再被引用 * 因此这时候 entry 也可以从 table 中清除 */ static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
在 ThreadLocalMap 中,也是用 Entry 来保存 K-V 结构数据的,不过 Entry 中的 key 只能是 ThreadLocal 对象,这点在构造方法中已经写死了。
另外,Entry 继承 WeakReference,也就是 key(ThreadLocal)是弱引用,其目的是将 ThreadLocal 对象的生命周期和线程生命周期解绑。