threadlocal機制的實現與thread和threadlocalmap密不可分
ThreadLocalMap
ThreadLocalMap是ThreadLocal的靜態內部類,內部由數組實現,默認大小16
private static final int INITIAL_CAPACITY = 16;
private Entry[] table;
Entry繼承自WeakReference,爲key-value形式,value爲我們要存的值,如Android中的Looper,key爲當前的ThreadLocal對象
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocal有兩個閾值,一個閾值是threshold,他的大小是當前數組大小的2/3,當超過這個值並且已用單元超過這個值得3/4是,會擴容,擴容爲原始2倍
threshold = len * 2 / 3;
if (size >= threshold - threshold / 4){
resize();
}
int newLen = oldLen * 2;
擴容是new了一個新數組,逐個重新hash
Entry[] newTab = new Entry[newLen];
set方法與get方法與hashmap類似,key爲threadlocal對象本身,value爲要存放的值如Looper,存放時,會根據threadlocal內部的一個hash值對數組取餘數定位到具體的index,如果相應位置不爲空或key和我們的不一樣,發生了碰撞,則逐個位置往下找,知道找到一個空位置
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);
Thread
thread內部持有ThreadLocalMap,這樣每個線程都會有一個自己的ThreadLocalMap
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal
ThreadLocal內部包含一個靜態原子變量,用於產生一個獨特的hash值,這樣每次new一個ThreadLocal,就會產生一個新的hash值,就可以實現存放多種變量,如一個線程即可以存Looper,也可以存放其他類
private final int threadLocalHashCode = nextHashCode();
private static AtomicInteger nextHashCode = new AtomicInteger();
private static final int HASH_INCREMENT = 0x61c88647;
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
set的時候,根據當前線程拿到當前線程的ThreadLocalMap
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
如果threadLocals爲空,就new一個出來
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
以當前ThreadLocal對象爲key進行查找
map.set(this, value);
get,remove之類的方法和set大同小異,不再廢話