ThreadLocal 源码分析
set方法
public void set(T value) {
// 获取当前线程对象即key
Thread t = Thread.currentThread();
// 获取当前线程的ThreadLocal.ThreadLocalMap
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
// 将key,value放入map中
map.set(this, value);
} else {
// 创建map
this.createMap(t, value);
}
}
getMap方法–获取当前线程的ThreadLocal.ThreadLocalMap
ThreadLocal.ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
set方法–将key,value放入map中
private void set(ThreadLocal<?> key, Object value) { ThreadLocal.ThreadLocalMap.Entry[] tab = this.table; int len = tab.length; // 做与运算计算value下标 int i = key.threadLocalHashCode & len - 1; // 通过开放寻址法找到tab中位置并放入 for(ThreadLocal.ThreadLocalMap.Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = (ThreadLocal)e.get();
// key相等覆盖当前Entry的值
if (k == key) {
e.value = value;
return;
}
// 将强引用转换为弱引用,并且将之前出现过数据冲突的数据做数据搬移
if (k == null) {
this.replaceStaleEntry(key, value, i);
return;
}
}
// 直接放入key,value
tab[i] = new ThreadLocal.ThreadLocalMap.Entry(key, value);
int sz = ++this.size;
// 将以当前位置以后的数据做数据搬移,超过负载因子rehash
if (!this.cleanSomeSlots(i, sz) && sz >= this.threshold) {
this.rehash();
}
}
replaceStaleEntry方法
private void replaceStaleEntry(ThreadLocal<?> key, Object value, int staleSlot) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;
int slotToExpunge = staleSlot;
ThreadLocal.ThreadLocalMap.Entry e;
int i;
// 以当前位置为起始位置,向前找,找到第一个key为null,但entry不为null
for(i = prevIndex(staleSlot, len); (e = tab[i]) != null; i = prevIndex(i, len)) {
if (e.get() == null) {
slotToExpunge = i;
}
}
// 将当前位置以及后面的数据做一个置null操作然后数据搬移
for(i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
ThreadLocal<?> k = (ThreadLocal)e.get();
if (k == key) {
e.value = value;
tab[i] = tab[staleSlot];
tab[staleSlot] = e;
if (slotToExpunge == staleSlot) {
slotToExpunge = i;
}
this.cleanSomeSlots(this.expungeStaleEntry(slotToExpunge), len);
return;
}
if (k == null && slotToExpunge == staleSlot) {
slotToExpunge = i;
}
}
tab[staleSlot].value = null;
tab[staleSlot] = new ThreadLocal.ThreadLocalMap.Entry(key, value);
// 清理向前为key null value不为null的,数据搬移
if (slotToExpunge != staleSlot) {
this.cleanSomeSlots(this.expungeStaleEntry(slotToExpunge), len); }
}
expungeStaleEntry方法
rehash数据搬移
private int expungeStaleEntry(int staleSlot) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;
tab[staleSlot].value = null;
tab[staleSlot] = null;
–this.size;
ThreadLocal.ThreadLocalMap.Entry e;
int i;
for(i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
ThreadLocal<?> k = (ThreadLocal)e.get();
if (k == null) {
e.value = null;
tab[i] = null;
--this.size;
} else {
int h = k.threadLocalHashCode & len - 1;
if (h != i) {
for(tab[i] = null; tab[h] != null; h = nextIndex(h, len)) {
}
tab[h] = e;
}
}
}
return i;
}
cleanSomeSlots方法
将值的强引用转换为弱引用
private boolean cleanSomeSlots(int i, int n) {
boolean removed = false;
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;
do {
i = nextIndex(i, len);
ThreadLocal.ThreadLocalMap.Entry e = tab[i];
if (e != null && e.get() == null) {
n = len;
removed = true;
i = this.expungeStaleEntry(i);
}
} while((n >>>= 1) != 0);
return removed;
}
createMap方法
hash槽创建
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
this.table = new ThreadLocal.ThreadLocalMap.Entry[16];
int i = firstKey.threadLocalHashCode & 15;
this.table[i] = new ThreadLocal.ThreadLocalMap.Entry(firstKey, firstValue);
this.size = 1;
this.setThreshold(16);
}
get方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
ThreadLocal.ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = e.value;
return result;
}
}
return this.setInitialValue();
}
getEntry方法
private ThreadLocal.ThreadLocalMap.Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & this.table.length - 1;
ThreadLocal.ThreadLocalMap.Entry e = this.table[i];
return e != null && e.get() == key ? e : this.getEntryAfterMiss(key, i, e);
}
getEntryAfterMiss方法
private ThreadLocal.ThreadLocalMap.Entry getEntryAfterMiss(ThreadLocal<?> key, int i, ThreadLocal.ThreadLocalMap.Entry e) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
for(int len = tab.length; e != null; e = tab[i]) {
ThreadLocal<?> k = (ThreadLocal)e.get();
if (k == key) {
return e;
}
if (k == null) {
// 数据搬移
this.expungeStaleEntry(i);
} else {
i = nextIndex(i, len);
}
}
return null;
}
setInitialValue方法
private T setInitialValue() {
T value = this.initialValue();
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
map.set(this, value);
} else {
this.createMap(t, value);
}
if (this instanceof TerminatingThreadLocal) {
TerminatingThreadLocal.register((TerminatingThreadLocal)this);
}
return value;
}
inheritableThreadLocals是使得子线程可以从父线程中得到值的设计的