set方法:
public void set(T value) {
// 获取当前的线程
Thread t = Thread.currentThread();
// 将当前的线程传递到getMap(Thread t)中
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
getMap(Thread t)方法:
ThreadLocalMap getMap(Thread t) {
// 这里就是隔离的真相了,是放到【当前】线程的 threadLocals 变量中。划重点:【当前】
return t.threadLocals;
}
这里出现一个新的对象 ThreadLocalMap
,下面看下ThreadLocalMap
是做什么用的
static class ThreadLocalMap {
//
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
// k当前ThreadLocal本身
super(k);
// 这里super的super是 Reference 抽象类
value = v;
}
}
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
private int size = 0;
private int threshold; // Default to 0
private void setThreshold(int len) {
threshold = len * 2 / 3;
}
// 这里是 ThreadLocal 存值的方法
// 这里的key是ThreadLocal自己本身this,value是真正要存储的值
private void set(ThreadLocal<?> key, Object value) {
// ThreadLocal基础结构是Entry[]数组
// 这里虽然是Entry[]数组,但是设置值只是用了一个位置(槽)
Entry[] tab = table;
//将当前ThreadLocal中的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;
}
}
// 如果之前没有覆盖值,直接赋新值
// new Entry(key,value)中的key是ThreadLocal自己本身this,value是真正要存储的值
tab[i] = new Entry(key, value);
int sz = ++size;
// size大小自增
// 如果超过大小,需要直接rehash,重新计算位置
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
private void remove(ThreadLocal<?> key) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
// 这段代码和set的一致,这里如果都满足,直接clear掉
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
if (e.get() == key) {
// 这里的e是Reference的子类,因为Entry是继承 WeakReference 类的
// WeakReference 类又继承抽象类 Reference
e.clear();
expungeStaleEntry(i);
return;
}
}
}
private boolean cleanSomeSlots(int i, int n) {
boolean removed = false;
Entry[] tab = table;
int len = tab.length;
do {
i = nextIndex(i, len);
Entry e = tab[i];
if (e != null && e.get() == null) {
n = len;
removed = true;
i = expungeStaleEntry(i);
}
} while ( (n >>>= 1) != 0);
return removed;
}
private void rehash() {
expungeStaleEntries();
// Use lower threshold for doubling to avoid hysteresis
if (size >= threshold - threshold / 4)
resize();
}
// 重新resize下
private void resize() {
Entry[] oldTab = table;
int oldLen = oldTab.length;
int newLen = oldLen * 2;
Entry[] newTab = new Entry[newLen];
int count = 0;
for (int j = 0; j < oldLen; ++j) {
Entry e = oldTab[j];
if (e != null) {
ThreadLocal<?> k = e.get();
if (k == null) {
e.value = null; // Help the GC
} else {
int h = k.threadLocalHashCode & (newLen - 1);
while (newTab[h] != null)
h = nextIndex(h, newLen);
newTab[h] = e;
count++;
}
}
}
setThreshold(newLen);
size = count;
table = newTab;
}
// 清理旧的Entry
private void expungeStaleEntries() {
Entry[] tab = table;
int len = tab.length;
for (int j = 0; j < len; j++) {
Entry e = tab[j];
if (e != null && e.get() == null)
expungeStaleEntry(j);
}
}
}
下面都是ThreadLocal
中的对象
private final int threadLocalHashCode = nextHashCode();
// 这里获取原子类的下一个
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
// 这里采用了原子类
private static AtomicInteger nextHashCode =
new AtomicInteger();
Reference
类中的clear方法:
public void clear() {
this.referent = null;
}