弱引用WeakReference作用与使用场景

在分析threadLocal源码时,发现有使用弱引用WeakReference,在之前总结GC的时候,也曾简单介绍java引用类型(《jvm GC算法类型》第6节),本文在详细总结下WeakReference的使用方法。

java 4种引用类型:

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

看下源码:

public class WeakReference<T> extends Reference<T> {

    /**
     * 创建一个弱引用,指向给定对象,不使用队列
     *
     * @param referent 弱引用指向的对象
     */
    public WeakReference(T referent) {
        super(referent);
    }

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

只有两个构造方法,不废话了,针对中两种构造放方法,直接上使用demo:

1. Demo
先看WeakReference第一种使用方式:

WeakReference(T referent)
public class WeakReferenceDemo {
    public static void main(String[] args) {
        //强引用
        RoleDTO role = new RoleDTO(1, "CEO");

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

//随便创建个对象
import lombok.Data;
@Data
@AllArgsConstructor
public class RoleDTO {
    private Integer id;
    private String type;
}


输出如下:

在这里插入图片描述

上述demo中,创建了两个对象,使用两种引用方式:

在这里插入图片描述

  • RoleDTO role = new RoleDTO();此role变量属于强引用,GC发生后,它指向的对象不被回收;通过后边打印,已经证明;
  • WeakReference< RoleDTO> weakReference= new WeakReference<>(new RoleDTO());此weakReference是弱引用,GC发生后,它指向的对象被回收,通过打印输出已经证明。

下面继续分析WeakReference第二种使用方式:

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

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

        System.out.println("GC执行前----");
        Reference<? extends RoleDTO> 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("弱引用指向的RoleDTO对象 已经被回收");
        }
        Reference<? extends RoleDTO> reference2;
        while ((reference2 = referenceQueue.poll()) != null) {
            //如果使用继承的方式就可以包含其他信息了
            System.out.println("referenceQueue中:" + reference2);
        }
 
    }
}

最后输出:
GC执行前----
GC执行后----
弱引用指向的RoleDTO对象 已经被回收
referenceQueue中:java.lang.ref.WeakReference@377dca04

执行前后,我们都打印了引用队列种的内容,GC之前没有打印输出;GC之后,弱引用被放入队列中,被打印输出。

2. 使用场景

  • 直接看ThreaLocal中的map实现(请参考一个场景Demo分析ThreadLocal使用方法和原理),此map继承了弱引用WeakReference,防止map中的key引用的对象无法被回收;
  • 除了ThreaLocal,还有一些高速缓存场景;因为缓存数据时用来加快执行速度,但是又不能无限制的将数据存入缓存,因为内存容量是有限的,这时可以使用弱引用,GC时及时清理缓存对象。


原文链接:https://blog.csdn.net/csdn_20150804/article/details/103748869

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中,对象的生命周期由垃圾回收器(GC)管理。为了让开发人员更好地控制对象的生命周期,Java 提供了三种不同类型的引用:强引用(Strong Reference)、软引用(Soft Reference)和弱引用Weak Reference)。它们之间的主要区别在于垃圾回收器对它们进行回收的时机和方式。 1. 强引用(Strong Reference) 强引用是最普通的引用类型,我们平常使用的引用默认都是强引用。如果一个对象具有强引用,那么垃圾回收器就不会回收这个对象,即使内存不足时也不会回收。当内存空间不足时,JVM 宁可抛出 OutOfMemoryError 错误,也不会回收具有强引用的对象。 2. 软引用(Soft Reference) 软引用是一种相对强引用弱化了一些的引用,需要用 SoftReference 类来实现。如果一个对象只有软引用,那么当内存空间不足时,垃圾回收器就可能会回收这个对象。软引用通常用于实现内存敏感的缓存,即缓存中的对象如果没有被使用,就可以被回收。 3. 弱引用Weak Reference弱引用是一种比软引用更弱化了一些的引用,需要用 WeakReference 类来实现。如果一个对象只有弱引用,那么当垃圾回收器进行扫描时,无论当前内存空间是否充足,都会回收这个对象。 弱引用通常用于实现一些缓存功能,如 ThreadLocal 中的缓存。另外,弱引用还可以用来解决内存泄漏问题,如监听器和回调中的对象引用,如果使用强引用,容易造成内存泄漏,使用弱引用可以及时释放不需要的对象。 总之,强引用是最常见的引用类型,能够保证对象的存活,但也容易造成内存泄漏;软引用适用于内存敏感的缓存场景,可以根据内存情况动态调整缓存大小;弱引用用于不需要强制保持对象存活的场景,如缓存、监听器等,可以有效防止内存泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值