版本
JDK8(JDK1.8)
ThreadLocal类源码重点
1.ThreadLocal类是用于创建线程私有变量的类,其原理是,在每个Thread类中都有一个ThreadLocalMap类,就是一个Hash表,而这个ThreadLocalMap以ThreadLocal为键,以线程私有变量为值,又由于每个Thread对象的ThreadLocalMap都不同,所以虽然只有同一个ThreadLocal对象,也可以在不同的线程中对应不同的值
2.从ThreadLocal的get方法就可以知道,为什么不同线程调用同一个ThreadLocal对象的get方法返回的值可以不一样,
因为get()方法一直获取的是当前线程中的ThreadLocalMap,不同线程的ThreadLocalMap是不一样的
public T get() {
// 获得当前运行线程
Thread t = Thread.currentThread();
// 取出当前线程内部的 ThreadLocalMap
ThreadLocalMap map = getMap(t);
// 如果线程内部的 ThreadLocalMap不为空
if (map != null) {
// 以当前ThreadLocal对象为为键,取出<ThreadLocal, Object>键值对
ThreadLocalMap.Entry e = map.getEntry(this);
// 如果键值对不为空
if (e != null) {
@SuppressWarnings("unchecked")
// 取出键值对中的值
T result = (T)e.value;
return result;
}
}
// 如果线程内部的 ThreadLocalMap为空,调用设置并获取初始值的方法
return setInitialValue();
}
注: 从上面可以看出ThreadLocalMap是惰性创建的,只有在使用ThreadLocal的get()、set()这些方法时才会尝试创建ThreadLocalMap,初始化代码如下
private T setInitialValue() {
// 获取初始值
T value = initialValue();
// 获取当前线程
Thread t = Thread.currentThread();
// 取出当前线程中的ThreadLocalMap
ThreadLocalMap map = getMap(t);
// 如果ThreadLocalMap不为空,则以当前ThreadLocal对象为键,初始值为值
// 将该键值对添加进ThreadLocalMap
if (map != null) {
map.set(this, value);
}
// 如果ThreadLocalMap为空
else {
// 创建 ThreadLocalMap对象
createMap(t, value);
}
// 如果该ThreadLocal对象原先属于TerminatingThreadLocal类或其子类
if (this instanceof TerminatingThreadLocal) {
// 则将其添加到Collection<TerminatingThreadLocal<?>> 中
// 用于线程结束时释放TerminatingThreadLocal<?>中的?资源
TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
}
// 返回初始值
return value;
}
3.ThreadLocal内存泄漏问题,因为ThreadLocalMap是由一个Entry数组实现的,Entry就是一个键值对类,如下,
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal.
* 与此ThreadLocal关联的值。
*/
Object value;
// 内存泄漏,ThreadLocal被GC回收了为null,则无法通过null取出value,
// 可以通过expungeStaleEntry回收键为null的Entry
Entry(ThreadLocal<?> k, Object v) {
// 键是弱引用,逃不过一次GC收集,软引用直到空间不足才回收
// 为什么设为弱引用,因为ThreadLocal一开始都会有强引用,
// 如果不想要了,设为null,则想GC收集它,如果不设为弱引用,则一直无法回收
super(k);
// 值是强引用,因为不清楚这个值会不会还有其他强引用,
// 如果没有,若设置为弱引用,则取出的值可能是null
value = v;
}
}
内存泄漏原因:

最低0.47元/天 解锁文章


被折叠的 条评论
为什么被折叠?



