文章目录
ThreadLocal
提供线程局部变量,每个线程都有自己独立初始化的变量副本
优点
- 实现线程间数据隔离
缺点
- 内存泄露
- 线程池重用会造成脏数据
成员变量
//固定hash值增量,使用该值散列出来的结果会比较平均
private static final int HASH_INCREMENT = 0x61c88647;
//当前线程ThreadLocal的hashcode
private final int threadLocalHashCode = nextHashCode();
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
//原子类整形来计算下一个ThreadLocal的hashcode
private static AtomicInteger nextHashCode = new AtomicInteger();
内部类
ThreadLocalMap
基本结构
static class ThreadLocalMap {
//内部节点类
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
//以ThreadLocal为key
Entry(ThreadLocal<?> k, Object v) {
//初始referent
super(k);
value = v;
}
}
//数组初始大小
private static final int INITIAL_CAPACITY = 16;
//使用一个Entry数组来保存ThreadLocal及对应的值
private Entry[] table;
//默认2/3*table.length,扩容阈值,当size>=3/4threshold时开始扩容
private int threshold;
}
重要方法
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue)
ThreadLocalMap的构造方法
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//初始数组大小
table = new Entry[INITIAL_CAPACITY];
//根据容量计算hash值
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
//赋值
table[i] = new Entry(firstKey, firstValue);
size = 1;
//设置阈值
setThreshold(INITIAL_CAPACITY);
}
set(ThreadLocal<?> key, Object value)
在Map中设置Threadlocal对应值
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
//根据数组容量计算hash获得当前ThreadLocal在数组中的位置
int i = key.threadLocalHashCode & (len-1);
//for循环遍历的原因:可能当前ThreadLocal由于hash冲突被放在了后面
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
//如果当前ThreadLocal相同则赋予新值
if (k == key) {
e.value = value;
return;
}
//hash冲突后第一个为null的位置插入
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
//如果循环中操作未成功,则在对应位置创建新节点
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
getEntry(ThreadLocal<?> key)
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
//可能存在索引冲突,从i之后遍历查找
return getEntryAfterMiss(key, i, e);
}
remove(ThreadLocal<?> key)
private void remove(ThreadLocal<?> key) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
//遍历,解决可能因冲突被放置在i后面的ThreadLocal
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
if (e.get() == key) {
e.clear();
//在Entry数组中删除当前位置的ThreadLocal
expungeStaleEntry(i);
return;
}
}
}
主要方法
initialValue
返回null,子类可以继承实现自定义初始值
protected T initialValue() {
return null;
}
set
将当前线程的此线程局部变量的副本设置为指定的值。
public void set(T value) {
Thread t = Thread.currentThread();
//获得线程t持有的threadLocals(ThreadLocal.ThreadLocalMap)
ThreadLocalMap map = getMap(t);
//如果Map已经初始化则赋值
if (map != null)
map.set(this, value);
else
//初始化map
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
//初始化线程持有的ThreadLocalMap
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
get
返回当前线程的此线程局部变量的副本中的值
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
//如果当前线程持有的map不为null
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//如果调用get时还未初始化线程中的Map则返回初始值并初始化Map
return setInitialValue();
}
//设置当前ThreadLocal的初始值
private T setInitialValue() {
//调用initialValue方法获得初始值
T value = initialValue();
//与set方法相同
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
remove
删除此线程局部变量的当前线程的值
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
//在ThreadLocalMap中删除当前ThreadLocal
m.remove(this);
}
ThreadLocal、Thread、ThreadLocalMap关系
线程持有ThreadLocalMap变量,在代码中调用对应ThreadLocal的方法时,线程会先获得ThreadLocalMap,然后ThreadLocalMap根据具体的ThreadLocal来进行处理。
InheritableThreadLocal
可以让子线程从父线程中取得值,子线程在获取值前父线程值改变,子线程获取的是父线程改变后的值。
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
protected T childValue(T parentValue) {
return parentValue;
}
//获得线程t的可继承ThreadLocal
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
//初始化线程t的inheritableThreadLocals
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
子线程继承ThreadLocal过程
//Thread类中初始化时代码,如果父类线程的inheritableThreadLocals 不为null则获得其ThreadLocal
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
private ThreadLocalMap(ThreadLocalMap parentMap) {
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
//创建一个新Entry数组,存放父线程中的值
table = new Entry[len];
//遍历将父线程中的inheritableThreadLocals复制到子线程
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
Object value = key.childValue(e.value);
Entry c = new Entry(key, value);
int h = key.threadLocalHashCode & (len - 1);
while (table[h] != null)
h = nextIndex(h, len);
table[h] = c;
size++;
}
}
}
}