ThreadLocal 结构

 
public
class Thread implements Runnable {

/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

  

public class ThreadLocal<T> {
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

  

  结合上面的图看,ThreadLocal是线程(Thread)的私有变量,所以不同线程之间的threadLocal变量是隔离出来的,只能同一个线程取。Thread下面有一个成员变量threadlocals指向着ThreadLocalMap(可以看成一个hashMap),Entry对象里面的keyvalue分别是ThreadLocal和对应的value值。

  ThreadLocal容易发生内存泄漏,当线程没有销毁,一直存在的时候,随着时间的延长,ThreadLocal里面的Entry会越来越多。(根可达性算法GC,线程(Thread)下的属性变量threadLocls无法被回收)

  原来 ThreadLocal 的 ThreadLocalMap 里面存的每一个 Entry 是一个 WeakReferenceWeakReference 会在 GC 的时候进行回收,回收的其实是 key,也就是弱引用的 referent, 然后  ThreadLocal 会在 set 和 get 的时候对 key 为空的 value 进行删除,所以这样就完美解决了当前线程生命周期不结束的时候,不同的 ThreadLocal 不停的追加到当前线程上面,导致内存溢出。

  所以使用完毕不用后应该调用ThreadLocal.remove() 移除entry,防止应为value的强引用导致无法被gc回收。

使用方法

 pulic static ThreadLocal<String> str = new ThreadLocal<>();


str.set("aaa");

str.get("aaa");

str.remove();

  

原文地址:https://www.cnblogs.com/chenfx/p/14380095.html