本文的目的是分析 ThreadLocal 的源码,关于 ThreadLocal 如何使用,请阅读参考资料1。
ThreadLocal.ThreadLocalMap
每个线程对象都有一个 ThreadLocalMap 类型的变量。ThreadLocalMap 是 ThreadLocal 的内部类,是用基于线性探测法的散列表实现的。每一个线程对象可以往 Map 中添加多个 ThreadLocal 对象为键的键值对,每个键对应的值唯一。所以通过一个 ThreadLocal 对象设置的值,在每个线程中都是唯一且互相独立的。唯一是因为键的唯一性,独立是因为每个线程都有自己的ThreadLocalMap内部变量,它是归线程所有的。
// java.lang.ThreadLocal.ThreadLocalMap
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
有趣的是它的元素是弱引用,被弱引用关联着的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被引用关联的对象。因此如果某个线程已经运行结束,不会因为这里有对它的引用而就无法回收,这个键会在回收后变成null。
所以在 ThreadLocalMap
的 set
方法中会调用 rehash
方法,rehash
方法先清理这些已经变成null的弱引用,对后面的部分Entry重新进行哈希散列,最后再判断是否扩容。(推荐阅读参考资料3)
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocal 构造器
public ThreadLocal() {
}
构造器为空。
ThreadLocal 的 set 方法
为当前线程的 ThreadLocalMap 对象添加键值对,