ThreadLocal详解

ThreadLocal是Java提供的线程局部变量,每个线程都可以通过ThreadLocal来存储各自的局部变量,这个局部变量对其他线程是不可见的。ThreadLocal为每个线程提供了一个独立的变量副本,各个线程之间互不影响

Java每个线程都有自己的ThreadLocalMap,里边存着自己私有的对象。Map的Entry里,key为ThreadLocal对象,value即为私有对象T

ThreadLocal 内存泄漏的原因

ThreadLocal可能会导致内存泄漏。这是由于ThreadLocal的设计和工作方式决定的。

ThreadLocal为每个线程存储了一个局部变量的副本,这个副本是存放在线程的 ThreadLocalMap 中,ThreadLocal 作为key,局部变量的副本作为value。重点在于,这个key(ThreadLocal对象)是对线程的 ThreadLocalMap 中的Entry采用了弱引用。

只要ThreadLocal对象没有被外部强引用所持有,在GC的时候该对象就会被回收,这样ThreadLocalMap中就会出现key为null的Entry,这种key为null的Entry就可能引发内存泄漏。

为什么会内存泄漏呢?因为虽然ThreadLocal已经被回收,但是ThreadLocalMap依然持有Entry的引用,Entry中有value,就导致这个Entry对象没有被回收,这样就导致了内存泄漏。

所以,在使用ThreadLocal的时候,一定要注意手动去调用ThreadLocal的 remove() 方法,清除当前线程中的局部变量。

为什么Entry是弱引用?

/**
 * 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;
    }
}

弱引用(Weak Reference):弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存

ThreadLocal使用弱引用(Weak References)来引用键(Key),这是一种设计上的权衡,旨在解决线程局部变量生命周期管理的问题。

ThreadLocal中,每个线程都持有一个ThreadLocalMap,而这个ThreadLocalMap使用ThreadLocal实例作为键来存储线程特定的值。如果使用强引用(Strong References)来引用这些键,那么只要线程是活的,这些键(即ThreadLocal对象)和对应的值都不会被垃圾回收器回收,即使外部已经没有对这些ThreadLocal对象的强引用了。这可能会导致内存泄漏,特别是在使用线程池的情况下,因为线程池中的线程通常是长时间存在的。

使用弱引用作为键的引用方式,则使得ThreadLocal对象可以被垃圾回收器回收,在ThreadLocal对象不再有其他地方的强引用时,即使线程本身还在运行,ThreadLocalMap中的相应条目的键会被回收。但这种设计同时引入了一种新的问题,即可能出现键为null的条目(因为键是弱引用,可能被垃圾回收器清除),但这些条目的值却可能长时间占用内存。为解决这个问题,ThreadLocalMap实现了一种清理机制,该机制会在访问ThreadLocalMap时清理键为null的条目。不过,完全依赖这种清理机制可能不够及时,因此还建议显式调用ThreadLocalremove()方法来及时清理不再使用的数据,尤其在使用完线程局部变量后。

总的来说,ThreadLocal使用弱引用主要是为了在ThreadLocal对象不再被使用时,能够让垃圾回收器有机会回收这些对象,以减轻内存泄漏的风险。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值