ThreadLocal内存泄漏

ThreadLocal原理
ThreadLocal并不是一个Thread,其内部有一个静态内部类ThreadLocalMap,而每一个 Thread 里都有一个 ThreadLocal.ThreadLocalMap 这样的类型变量,该变量的名字叫作 threadLocals,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。即同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。(每个线程有自己的变量副本,所以不会存在多线程共享问题

ThreadLocal内存泄漏分析


  static class ThreadLocalMap {
 
        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
 
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }     
    }

上面是ThreadLocalMap 的部分源码,可以看到内部是一个Entry 继承了WeakReference弱引用,弱引用的特点是,如果这个对象只被弱引用关联,而没有任何强引用关联,那么这个对象就可以被回收,所以弱引用不会阻止 GC,所以key会被回收。但是value = v对应的value是一个强引用,还是存在的,这就可能造成内存泄漏(因为这个时候ThreadLocalMap会存在keynull但是value不为nullentry项)。

如何避免内存泄漏
通过上面分析可知,ThreadLocal内存泄漏的原因不在key,而在于value,所以需要在使用完ThreadLocal时需要删除value对象。
ThreadLocal本身就提供了remove方法,可以将ThreadLocalMap 对应的value一起清除掉。

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}
  • 每次使用完ThreadLocal都调用remove()方法清除数据
  • 将ThreadLocal变量定义成private static,这样能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉value。
private static ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<>();

另外,为什么都说每次使用完ThreadLocal都要调用remove呢?因为通常我们都会使用线程池,而当一个请求使用完某个线程,该线程会回到线程池被其它请求使用,就可能会出现不同的请求使用到同一个线程,及时的清除掉也可以避免不同请求之间的数据污染

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值