ThreadLocal
ThreadLocal变量又可以称为线程变量,ThreadLocal内部实现为每一个线程保存了一份副本变量。
每一个线程都有一个map对象,map对象中存放了ThreadLocal对象的副本变量。
set方法详解
public void set(T value) {
//拿到当前线程
Thread t = Thread.currentThread();
//获取当前线程的ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
getMap方法返回线程的threadLocals变量
ThreadLocalMap getMap(Thread t) {
return t.threadLocals变量;
}
查看Thread的182行有一个ThreadLocalMap threadLocals变量,188有一个InheritableThreadLocal变量。
class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
上面可以看到每一个线程中都有ThreadLocalMap对象,再看看是ThreadLocal是怎么赋值的。在set的时候判断map==null,走创建map流程。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
查看ThreadLocalMap(this, firstValue)这个构造方法。
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
看下以下的一个结构图,ThreadLocalMap他自己又有一个
是ThreadLocal的一个内部类,而ThreadLocalMap他自己又有一个Entry内部类。~~~~
看Entry类,继承了WeakReference,是一个弱引用。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
再继续看ThreadLocalMap
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
内部有一个Entry[] table,key就是变量自己、value就是变量的副本。
get方法
每一个线程有一个map,这个map存放了threadLocal对象的副本变量。查看get方法是如何获取变量的。
//获取当前线程的map,从map对象里获取到entry对象,并将其中的value返回。
public T get() {
//当前线程
Thread t = Thread.currentThread();
//拿到当前线程的map(ThreadLocalMap)对象。
ThreadLocalMap map = getMap(t);
if (map != null) {
//获取entry对象,this是threadlocal对象
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
//获取value并返回
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
remove方法
再使用完threadlocal之后记得主动的remove变量。
获取map对象,调用内部的remove方法。
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
获取当前的table,移除当前key对应的entry。
private void remove(ThreadLocal<?> key) {
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)]) {
if (e.get() == key) {
e.clear();
expungeStaleEntry(i);
return;
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。