ThreadLocal
JDK17的ThreadLocal部分源码
ThreadLocal中的源码
public class ThreadLocal<T> {
//无参构造
public ThreadLocal() {
}
//Get方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//如果当前线程不存在ThreadLocalMap实例就创建一个,并且值设置为null
return setInitialValue();
}
//初始化方法
private T setInitialValue() {
//初始化Value, 其实就是返回一个null
T value = initialValue();
Thread t = Thread.currentThread();
//获取Thread中的ThreadLocalMap
ThreadLocalMap map = getMap(t);
//如果当前Thread中存在ThreadLocalMap,即设置为null
if (map != null) {
map.set(this, value);
} else {
//不存在就创建ThreadLocalMap
createMap(t, value);
}
if (this instanceof TerminatingThreadLocal) {
TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
}
return value;
}
//ThreadLocalMap的创建方法 ThreadLocalMap是针对Thread的。
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//set方法,直接ThreadLocalMap中的set方法,同理都是获取到当前线程的ThreadLocalMap对象,然后后将值设置进去。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
}
ThreadLocalMap类,在JDK17中式在ThreadLocal.java文件里面的内部类
static class ThreadLocalMap {
//这是ThreadLocalMap中的table变量,其实ThreadLocalMap由多个Entry组成,就像是HashTable一样。
private Entry[] table;
//默认table的初始容量。
private static final int INITIAL_CAPACITY = 16;
//所以entry式弱引用
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
//这是set方法
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
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)]) {
if (e.refersTo(key)) {
e.value = value;
return;
}
if (e.refersTo(null)) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
}
JavaGuide中的图片这张图很清楚的表明了ThreadLocal存储具体的结构