WeakReference作用及使用场景

java引用

ThreadLocalMap实现使用了WeakReference,为啥ThreadLocalMap的Entry要继承WeakReference,有什么作用?

首先java有4种引用类型:

强:A a=new A(); 此时引用a强引用对象A;不会被GC;
软:SoftReference.java,在内存不够时引用对象会被GC;
弱:WeakReference.java,每次GC都会被回收;
虚:PhantomReference.java,每次GC都会被回收;

WeakReference的作用就是保证每次GC时,该引用对象都会被回收。

再看ThreadLocalMap的Entry实现

        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,防止map中的key引用的对象无法被回收;

WeakReference

WeakReference有两个构造函数

public class WeakReference<T> extends Reference<T> {
//创建一个弱引用,指向给定对象;
    public WeakReference(T referent) {
        super(referent);
    }

//创建一个弱引用,指向给定对象;引用在指定队列中注册
    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

Demo验证

WeakReference

extends Reference

创建一个弱引用,指向给定对象,GC后该对象将被回收。

public class WeakReferenceDemo {

    public static void main(String[] args) {
        //强引用
        Role role = new Role(1, "CEO");

        //弱引用
        WeakReference<Role> weakReference = new WeakReference<>(new Role(1, "CTO"));
        //主动触发GC
        System.gc();
        try {
            //给GC留点时间,保证GC执行完成
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (role == null) {
            System.out.println("强引用指向的Role对象 已经被回收");
        }

        //weakReference.get()获取弱引用指向的对象,如果对象是null,表示被回收
        if (weakReference.get() == null) {
            System.out.println("弱引用指向的Role对象 已经被回收");
        }

    }

}

//output
弱引用指向的Role对象 已经被回收

WeakReference(T referent, ReferenceQueue<? super T> q) 这个构造方法多了个参数,是个引用队列类型;GC后,被弱引用指向的对象被回收,同时这些弱引用将会被添加的这个引用队列当中。

public class WeakReferenceQueueDemo {
    public static void main(String[] args) {
        ReferenceQueue<Role> referenceQueue = new ReferenceQueue<>();
        WeakReference<Role> weakReference = new WeakReference<>(new Role(3, "CFO"), referenceQueue);

        System.out.println("GC执行前----");
        Reference<? extends Role> reference;
        while ((reference = referenceQueue.poll()) != null) {
            //如果使用继承的方式就可以包含其他信息了
            System.out.println("referenceQueue中:" + reference);
        }

        System.gc();
        try {
            //给GC留点时间,保证GC执行完成
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("GC执行后----");
        if (weakReference.get() == null) {
            System.out.println("弱引用指向的Role对象 已经被回收");
        }
        Reference<? extends Role> reference2;
        while ((reference2 = referenceQueue.poll()) != null) {
            //如果使用继承的方式就可以包含其他信息了
            System.out.println("referenceQueue中:" + reference2);
        }

    }

}
//output
GC执行前----
GC执行后----
弱引用指向的Role对象 已经被回收
referenceQueue中:java.lang.ref.WeakReference@7e0babb1

使用场景

除了ThreaLocal,还有一些高速缓存场景;因为缓存数据时用来加快执行速度,但是又不能无限制的将数据存入缓存,因为内存容量是有限的,这时可以使用弱引用,GC时及时清理缓存对象。

0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x