我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码
一、架构图
二、为什么会内存泄漏?
- 看下图,当 threadLocal1,threadLocal2,threadLocal3 = null的时候,table中 Entry的引用依然还在。假如thread01,thread02,一直不结束。那么Entry中的引用会一直存在(thread01Ref->Thread01->threadLocalMap01->entry->valueRef->valueMemory), 导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉,但是该value永远不能被访问到,这样就存在了内存泄漏。
=== 点击查看top目录 ===
三、ThreadLocal的Entry 为什么要用 weakReference ?
- ThreadLocal.ThreadLocalMap.Entry
public class ThreadLocal<T> {
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
}
- Thread
public java.lang.class Thread implements Runnable {
...
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
...
}
- Thread的 exit 方法
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* !!!看这里!!! */
threadLocals = null;
/* !!!看这里!!! */
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
Thread#exit方法会把内部的threadLocals设置为 null,threadLocalMap生命周期实际上thread的生命周期相同。
3.1 为什么ThreadLocal不用强引用?
- 因为weakReference 能够一定程度上避免内存泄漏
当Thread一直存在,threadLocal1,threadLocal2,threadLocal3 = null的时候。GC看到 threadLocal1,threadLocal2,threadLocal3 指向的对象的只有 weakReference 引用的时候,会将