ThreadLocal原理的通俗解释

73 阅读1分钟

ThreadLocal原理

Thread类中有ThreadLocalMap。ThreadLocalMap是HashMap的ThreadLocal定制版。 ThreadLocal中存的东西实际上是存在当前Thread中的ThreadLocalMap中。存东西的过程: 1)拿当前Thread 2)拿当前Thread的ThreadLocalMap(懒加载) 3)操作ThreadLocalMap

public class Thread implements Runnable {
    //......
    //与此线程有关的ThreadLocal值。由ThreadLocal类维护
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    //......
}

ThreadLocal类的set()方法


public void set(T value) {
    //获取当前请求的线程
    Thread t = Thread.currentThread();
    //取出 Thread 类内部的 threadLocals 变量(哈希表结构)
    ThreadLocalMap map = getMap(t);
    if (map != null)
        // 将需要存储的值放入到这个哈希表中
        map.set(this, value);
    else
        createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

image.png

内存泄漏问题

ThreadLocalMap的key被设计成是弱引用,但是value依然是强引用(因为将map的value设置成弱引用时不合理的)。弱引用会在GC时被回收(虽然GC线程优先级不高),而强引用不会,导致出现key=null,value<>null的键值对。导致value出现内存泄漏。虽然,ThreadLocal在调用 set()get()remove() 方法的时候,会清理掉 key 为 null 的记录。但是使用完 ThreadLocal方法后最好手动调用remove()方法。

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}