持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
类定义
首先看ThreadLocal 的类定义上,是带有泛型标注的,说明ThreadLocal 可以存储任意类的数据。
public class ThreadLocal<T> {}
ThreadLocal的属性:
private final int threadLocalHashCode = nextHashCode();
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
private static AtomicInteger nextHashCode = new AtomicInteger();
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
private int threshold;
}
......
-
threadLocalHashCode 表示当前 ThreadLocal 的 hashCode,主要用于计算当前 ThreadLocal对象 在 ThreadLocalMap 中的索引位置
-
nextHashCode() 主要是用于计算 ThreadLocal对象 的 hashCode 值
-
nextHashCode 属性使用了static修饰,并且数据类型是AtomicInteger,首先AtomicInteger保证了每个ThreadLocal的threadLocalHashCode 是唯一的,当然这必须得在不同JVM中;其次static可以使得在同一时刻,多个ThreadLocalMap被set到ThreadLocal时,需要使用到threadLocalHashCode进行唯一区分
-
ThreadLocalMap中的Entry表示数组中的每个节点值,继承了WeakReference,表示当前对象在没有引用指向时,进行JVM垃圾回收时就会被回收掉
-
ThreadLocalMap 的数组的初始化大小为16,扩容的初始阈值是数组大小的三分之二
ThreadLocalMap的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();
}
int i = key.threadLocalHashCode & (len-1); 表示计算 key 在数组中的下标,其实就是 ThreadLocal 的 hashCode 和数组大小-1取余
for循环数组进行处理时 tab[i],首先查看 i 索引位置有没有值,有值的话,索引位置 + 1,直到找到没有值的位置
e = tab[i = nextIndex(i, len)])... nextIndex 就是让在不超过数组长度的基础上,把数组的索引位置 + 1
if (k == key) { e.value = value; return; } 找到内存地址一样的 ThreadLocal,直接替换
if (k == null) { ... } 判断当前 key 是否是 null,是则说明 ThreadLocal 被清理了,直接替换掉
set方法中用到了AtomicInteger类,Atomic相关的类主要用于线程不安全的情况下,做原子级别的递增,因为本身的递增操作是读取原值,+1后重新赋值,在线程不安全的情况下极有可能会发生递增值与预期不匹配。