ThreadLocal是为了实现在一个线程中可以在不同阶段访问同一个数据,同时隔离其他线程,不同于普通全局变量,可能会有不同的线程访问同一个全局变量,导致数据的不安全
ThreadLocal是利用一个线程维护一个ThreadLocalMap,
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadlocalMap是Thread的Threadlocals属性进行存放,当一个线程销毁时ThreadLocal也会随着销毁
早于JDK1.8时,是通过ThreadLocal进行对ThreadLocalMap的维护,但是ThreadLocal若是在Web项目中是服务器关闭后才会销毁,那么ThreadLocalMap会存在很长一段时间,当过多的时候会占用太多内存
另外一点不同之处是1.8之前Entry中的key是Thread,后来是ThreadLocal,首先知道ThreadLocal set和get存取数据时是通过
Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1);
来确定该Entry在数组中的index,如果key是Thread,那么会导致一个线程只能有一个Entry,Entry[]能存的数据就会很少
ThreadLocalMap和Entry都是ThreadLocal的静态内部类
Entry[] table是ThreadLocalMap的属性
他们之间的逻辑关系是一个线程维护一个threadLocalMap,其中的table数组存储一个线程的不同threadLocal
static class Entry extends WeakReference> { Object value; Entry(ThreadLocal> k, Object v) { super(k); value = v; } }
Entry继承的是弱引用,他的Key即是弱引用,value还是强引用,在remove时会将key=null,然后在每次set和get时会将key值没null的value清除。
public void clear() {
this.referent = null;
}
referent即是key
set()
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
map.set()
private void set(ThreadLocal> key, Object value) {
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)]) {
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);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
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;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
if (this instanceof TerminatingThreadLocal) {
TerminatingThreadLocal.register((TerminatingThreadLocal>) this);
}
return value;
}



