ThreadLocal实现原理以及防止内存泄漏

  ThreadLocal是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据。

实现原理:
public class Threadlocal {
    static ThreadLocal<Person> tl = new ThreadLocal<>();
    public static void main(String[] args) {
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(tl.get());
        }).start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tl.set(new Person());
        }).start();
    }

    static class Person{
        String name = "zhangsan";
    }
}

  上述程序,创建了两个线程,线程1将Person对象存储进ThreadLocal对象,线程2通过ThreadLocal对象获取存进去的Person对象,但是线程2永远都获取不到Person对象。我们查看ThreadLocal对象的set()方法源码,首先获取当前线程,然后拿到当前线程的ThreadLocalMap,该map以ThreadLocal对象为key,set的值为value,所以某个线程存储在ThreadLocal对象中的value只能在当前线程中获取。

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
防止内存泄漏
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,所以该Entry的key,即ThreadLocal对象是一个虚引用,这里为什么要用虚引用呢?
在这里插入图片描述
  如图所示,堆中的ThreadLocal对象一共有两个引用指向它,一个是强引用tl,另一个是虚引用ThreadLocalMap中的key。如果不用虚引用,当强引用tl消失时,还会存在另外一个强引用key,那么这个ThreadLocal将不会被虚拟机回收,会造成内存泄漏。但是,即使ThreadLocal对象被回收后,value依旧存储在ThreadLocalMap中,只是key为null,永远不能被访问,还是会造成内存泄漏。所以当ThreadLocal对象不再使用后,需要执行remove()方法。

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null){
        m.remove(this);
    }
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值