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大同小异,不再废话