JDK源码(二十):ThreadLocal
Posted jdkSpring
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK源码(二十):ThreadLocal相关的知识,希望对你有一定的参考价值。
实现原理
ThreadLocalMap
static class Entry extends WeakReference<ThreadLocal<?>> {
/** 与此ThreadLocal关联的值. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
Entry继承自WeakReference,可以知道,ThreadLocalMap是使用ThreadLocal的弱引用作为Key的。如果一个ThreadLocal没有外部关联的强引用,那么在虚拟机进行垃圾回收时,这个ThreadLocal会被回收,这样,ThreadLocalMap中就会出现key为null的Entry,这些key对应的value也就再无妨访问,但是value却存在一条从Current Thread过来的强引用链。因此只有当Current Thread销毁时,value才能得到释放。
ThreadLocalMap采用线性探查的方式来处理哈希冲突,所以会有一个while循环去查找对应的key,在查找过程中,若发现key为null,即通过弱引用的key被回收,会调用expungeStaleEntry(int)方法,若key为null,则该方法会清理与key对应的value以及Entry。
类名
public class ThreadLocal<T>
变量
set(T value)
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);
}
当map为null时,调用createMap创建一个map。
createMap(Thread t, T firstValue)
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
可以看出createMap是初始化当前线程的threadLocals变量。所以并不是ThreadLocal中存储线程,而是线程中存储ThreadLocal。
get()
public T get() {
//返回当前正在执行的线程对象的引用
Thread t = Thread.currentThread();
//获取线程对应的ThreadLocalMap对象
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
简单应用
很多时候我们会用SimpleDateFormat来格式化时间,而SimpleDateFormat其实是线程不安全的,我们可以用ThreadLocal封装一个时间工具类。
ThreadLocal源码(jdk1.8)
以上是关于JDK源码(二十):ThreadLocal的主要内容,如果未能解决你的问题,请参考以下文章
ThreadLocal深入JDK源码之ThreadLocal类