ThreadLocal
一、ThreadLocal的实现原理
Thread
有一个内部变量ThreadLocal.ThreadLocalMap
,这个类是ThreadLocal
的静态内部类,它的实现与HashMap
类似,当线程第一次调用ThreadLocal
的get/set
方法时会初始化它。它的键是这个ThreadLocal
对象本身,值是需要存储的变量。也就是说ThreadLocal
类型的本地变量是存放在具体的线程空间里。当不断的使用get
方法获取时,是到线程独有线程空间中获取变量,使得其他线程无法访问到,也就达到了线程安全的目的。在使用完成之后,可以通过remove
方法,移除不使用的本地变量。
ThreadLocal和同步机制的比较
如果说同步机制是一种以时间换空间的做法,那么ThreadLocal
就是一种以空间换时间的做法,在同步机制下,当访问共享变量时,同步机制保证了同一个时刻只能有一个线程访问到,其他线程进入阻塞。ThreadLocal
下,为每个线程都复制了共享变量的副本,也就不存在共享变量的说法。
二、源码
1.set()
通过
ThreadLocal
的set方法调用到ThreadLocal.ThreadLocalMap
静态内部类的set方法。
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 若对象为空,则初始化threadLocalMap对象
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
static class ThreadLocalMap {
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
// 先通过hashcode作为下标取数组对应位置的值,若为空,设置值。
// 若不为空,往后移动一个位置,如果获取到的长度等于数组长度,从0位置查找。
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