ThreadLocal

ThreadLocal

多线程中对于解决线程安全的一个操作类

为每个线程都分配一个独立的ThreadLocal对象副本

实现了线程间的数据隔离
//创建ThreadLocal对象,定义对象内资源的类型
ThreadLocal<String> tl = new ThreadLocal<>();

set()//向对象中存入值,每个线程独立
get()//获取对象中的值,每个线程独立
remove()//清除

ThreadLocal实现原理

Thread类

thread类中维护了一个ThreadLocal的内部类ThreadLocalMap对象

ThreadLocalMap对象中维护了一个Entry数组

即每个线程中都维护了一个独立的Entry数组

我们将线程间独立的数据存储在这个Entry数组中

以ThreadLocal对象作为key,value作为值

这样就实现了同一个ThreadLocal对象的数据隔离

ThreadLocal.ThreadLocalMap threadLocals = null;

Set

public void set(T value) {
    //获取当前的线程对象
        Thread t = Thread.currentThread();
    //根据线程对象获取对应的map
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

get

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

ThreadLocal的内存泄漏问题

因为ThreadLocalMap中的key是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;
            }
        }
}

所以当ThreadLocal对象没有任何的强引用时

(ThreadLocal变量被手动置为空)

,就会在下一次GC时被手动回收

就导致ThreadLocalMap中出现了一个key为null的Entry

无法访问对应的value,同时Entry又不会被GC回收

导致内存泄漏

内存泄漏:

资源不会被程序用到,同时也无法被GC回收

为什么不使用强引用

强引用会导致ThreadLocal对象被回收时,key不会被回收,出现内存泄漏问题

而弱引用虽然也会导致内存泄漏,但可以在下一次set/get/remove时检查nullkey进行清除

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值