一、ThreadLocal
用于在一个线程中传递同一个对象,原理是在每个线程内部维护一个内存空间,存储线程独享的变量。
二、代码示例及源码阅读
1.示例
代码如下:
public class TheadLocalTest extends Thread{
ThreadLocal<String> tl1 = new ThreadLocal<>();
ThreadLocal<String> tl2 = new ThreadLocal<>();
public static void main(String[] args) {
Thread t = new TheadLocalTest();
t.start();
}
@Override
public void run() {
set(tl1, "测试1");
set(tl2, "测试2");
System.out.println("tl1:"+get(tl1));
System.out.println("tl2:"+get(tl2));
}
private void set(ThreadLocal<String> threadLocal, String value){
threadLocal.set(value);
}
private String get(ThreadLocal<String> threadLocal){
return threadLocal.get();
}
}
运行结果:
tl1:测试1
tl2:测试2
2.源码阅读
代码如下:
//ThreadLocal构造方法
public ThreadLocal() {
}
//set方法
public void set(T value) {
//取得当前线程对象
Thread t = Thread.currentThread();
//从当前线程对象上取得ThreadLocalMap,即取得数据实际内存空间的引用
ThreadLocalMap map = getMap(t);
if (map != null)
//不为null,则插入或更新
map.set(this, value);
else
//否则创建一个ThreadLocalMap对象
createMap(t, value);
}
//getMap方法
ThreadLocalMap getMap(Thread t) {
//返回线程私有的threadLocals
return t.threadLocals;
}
//creadMap方法,赋值
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//静态内部类ThreadLocalMap的构造方法
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//内部维护一个Entry数组存储数据,默认大小为16
table = new Entry[INITIAL_CAPACITY];
//通过hash位运算获得存储数据的位置
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
//设置已存储的数量
size = 1;
//设置resize的阈值
setThreshold(INITIAL_CAPACITY);
}
//静态内部类ThreadLocalMap的set方法
private void set(ThreadLocal<?> key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
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();
//找到key,赋值
if (k == key) {
e.value = value;
return;
}
//存在作为key的threadlocal已被设null或回收的情况
if (k == null) {
//对过期失效数据进行清洗并设置
replaceStaleEntry(key, value, i);
return;
}
}
//未找到key,则直接赋值
tab[i] = new Entry(key, value);
int sz = ++size;
//判断是否需要调整数组大小
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
//threadlocal的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;
}
}
//未找到数据,返回值为null
return setInitialValue();
}
//setInitialValue方法
private T setInitialValue() {
//即赋null值
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
总结
如有错漏,敬请指出。