一 点睛
在分析 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 的解读
/**
* 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 对象的生命周期和线程生命周期解绑。