Java中的四种引用

java中四种引用:
a.强引用
平常我们代码中写到的引用类型都是强引用类型,比如Object obj = new Object();, Object实例就有一个强引用类型指向它,在GC过程中即使发生OOM,该Object实例都不会被回收。

b. 软引用 - SoftReference
定义方式:SoftReference sr = new SoftReference(new Object()); 一个对象的实例被一个软引用实例指向,那么在GC过程中发生OOM之前,该Object对象实例会被回收掉,在内存充足的情况下是不会被回收的。同时可以将一个引用队列关联到该软引用上,在软引用指向的对象被回收后,该软引用会被加入到关联的引用队列中。我们可以通过Reference的get()方法获取到该软引用指向的对象实例。

c. 弱引用 - WeakReference
弱引用基本上同上面的软引用类似,WeakReference wr = new WeakReference(new Object());,但是特殊点就是在它被创建后的下一次GC时候其指向的对象实例会被回收掉,不管内存是不是充足,反正就是活不过一次GC。JDK中的WeakHashMap就是使用到WeakReference,其Key就是被包装成WeakReference。

d. 虚引用 - PhantomReference
定义方式:PhantomReference pr = new PhantomReference(new Object(), new ReferenceQueue()),虚引用对象再被定义时,必须指定一个引用队列实例。JDK文档中介绍它主要用于对象被回收前资源的释放操作,替换finalize()方法。它和前面的两个软引用和弱引用不同的地方有两点:

在看ThreadLocal源码的时候,其中嵌套类ThreadLocalMap中的Entry继承了WeakReferenc,为了能搞清楚ThreadLocal,只能先了解下了WeakReferenc,以及其他的三种引用。

主要先谈下弱引用
WeakReference如字面意思,弱引用, 当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果这时GC运行, 那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收。

首先先来看下WeakReference中的构造函数

public class WeakReference<T> extends Reference<T> {
    public WeakReference(T referent) {
        super(referent);
    }

    public WeakReference(T referent, ReferenceQueue<? super T> queue) {
        super(referent, queue);
    }

}

WeakReference(T referent)
referent就是被弱引用的对象(注意区分弱引用对象和被弱引用的对应,弱引用对象是指WeakReference的实例或者其子类的实例),比如有一个Apple实例apple,可以如下使用,并且通过get()方法来获取apple引用。也可以再创建一个继承WeakReference的类来对Apple进行弱引用,下面就会使用这种方式。

WeakReference<Car> appleWeakReference = new WeakReference<>(car);
Car car1 = appleWeakReference.get();
public class Test {

    public static void main(String[] args) {
        Audi audi = new Audi(new Car("奥迪"));
        System.out.println(audi.get());
        System.gc();
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        //检查是否为空被回收

        if (audi.get() == null){
            System.out.println("已经被清除");
        }
    }
}

输出如下:

Car{name='奥迪'}
[GC (System.gc()) [PSYoungGen: 3084K->696K(35840K)] 3084K->704K(117760K), 0.0186270 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 
[Full GC (System.gc()) [PSYoungGen: 696K->0K(35840K)] [ParOldGen: 8K->618K(81920K)] 704K->618K(117760K), [Metaspace: 3225K->3225K(1056768K)], 0.0250364 secs] [Times: user=0.02 sys=0.00, real=0.03 secs] 
Car:  奥迪finalize
已经被清除
  • WeakReference(T referent, ReferenceQueue<? super T> queue)
    与上面的构造方法比较,多了个ReferenceQueue,在对象被回收后,会把弱引用对象,也就是WeakReference对象或者其子类的对象,放入队列ReferenceQueue中,注意不是被弱引用的对象,被弱引用的对象已经被回收了。
public class Test2 {
    public static void main(String[] args) {
        ReferenceQueue<Car> referenceQueue = new ReferenceQueue<>();
        WeakReference<Car> carWeakReference =new WeakReference<Car>(new Car("奥迪"),referenceQueue);
        WeakReference<Car> carWeakReference1 = new WeakReference<Car>(new Car("奔驰"),referenceQueue);

        System.out.println("=====调用GC前=====");
        Reference<? extends Car> reference = null;
        while ((reference = referenceQueue.poll()) != null){
            System.out.println(reference);
        }
        System.out.println(carWeakReference);
        System.out.println(carWeakReference1);
        System.out.println(carWeakReference.get());
        System.out.println(carWeakReference1.get());

        System.out.println("=====调用GC===");
        System.gc();
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

        System.out.println(carWeakReference.get());
        System.out.println(carWeakReference1.get());

        Reference<? extends Car> reference1 = null;

        while((reference1 = referenceQueue.poll()) != null){
            System.out.println("referenceQueue:"+reference1);
        }
    }
}

输出:

=====调用GC前=====
java.lang.ref.WeakReference@74a14482
java.lang.ref.WeakReference@1540e19d
Car{name='奥迪'}
Car{name='奔驰'}
=====调用GC===
Car:  奔驰finalize
Car:  奥迪finalize
null
null
referenceQueue:java.lang.ref.WeakReference@74a14482
referenceQueue:java.lang.ref.WeakReference@1540e19d

可以看到在队列中(ReferenceQueue),调用gc之前是没有内容的,调用gc之后,对象被回收了,并且弱引用对象appleWeakReference和appleWeakReference2被放入了队列中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值