强弱软虚引用

强引用,最普遍的情况,String s = “abc”,这个 s 就是强引用,只要强引用存在,对象就不会被垃圾回收器回收。

软引用SoftReference,用于还有用但非必须的对象,内存足够,则不会回收,内存不足,就会被回收掉
实现场景是用于内存敏感的高速缓存。软引用一般与引用队列联合使用。当软引用的对象被回收时,jvm 会将软引用加入到与之关联的引用队列中。

弱引用WeakReference,与软引用差不多,与软引用的区别是,无论内存是否足够,只要垃圾回收器线程在扫描的区域中发现了弱引用对象,直接回收掉他的内存

虚引用,也叫幻影引用。与没有引用的对象一样,不会对对象的声明周期产生影响。虚引用主要功能是,追踪对象被垃圾器回收的活动。虚引用最重要的一个特征是,虚引用必须和引用队列联合使用,当虚引用的对象被垃圾回收之前,会把虚引用加入到引用队列中。


使用场景:
1、利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题;

2、通过软引用对象重获方法实现java对象的高速缓存:比如我们创建了一个Employee类,如果每次需要查询一个雇员的信息。哪怕是几秒钟之前刚刚查询过的,都要重新构建一个实例,这是需要消耗很多时间的。我们可以通过软引用和HashMap的结合,先是保存引用方面:以软引用的方式对一个Employee对象的实例进行引用并保存该引用到HashMap上,key为此雇员的id,value为这个对象的软引用,另一方面是取出引用,缓存中是否有该Employee实例的软引用,如果有,从软引用中取得 。如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,并保存对这个新建实例的软引用;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

/**
 * @author gaoyang
 * @create 2020-09-04 9:18
 */
public class 强弱软虚引用 {
    public static void main(String[] args) throws Exception {
        soft();
        System.out.println("--------------------");
        weak();
    }
    /**
     * 软引用,用于还有用但非必须的对象,内存足够,则不会回收,内存不足,就会被回收掉。
     * 实现场景是用于内存敏感的高速缓存。软引用一般与引用队列联合使用。
     * 当软引用的对象被回收时,jvm 会将软引用加入到与之关联的引用队列中。
     * @throws InterruptedException
     */
    public static  void soft() throws InterruptedException {
        Object obj = new Object();
        ReferenceQueue rq = new ReferenceQueue();//创建关于obj的软引用,使用引用队列
        SoftReference sr = new SoftReference(obj, rq);

        System.out.println(sr.get()); //get方法会输出这个obj对象的hashcode
        System.out.println(rq.poll());//输出为null

        obj = null;
        System.gc();
        Thread.sleep(2000);

        //由于此时内存并没有满,所以即使 调用了gc,软引用的对象也不会被回收,
        //所以rq.poll 也只会 输出null
        System.out.println(sr.get()); //因为堆空间没满,可有可无的特性,所以还是会输出这个obj对象的hashcode
        System.out.println(rq.poll());//队列为null

    }

    /**
     * 具有弱引用的对象拥有的生命周期更短暂。
     * 因为当JVM进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。
     * 不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象
     * @throws Exception
     */
    public static void weak() throws Exception{
        Object obj = new Object();
        ReferenceQueue rq = new ReferenceQueue<>();
        WeakReference wr = new WeakReference(obj,rq);
        System.out.println(wr.get());
        System.out.println(rq.poll());
        obj = null;
        System.gc();
        Thread.sleep(200);
        //弱引用,只要gc就会被回收,所以wr会输出null,弱引用的对象也会被放进rq队列中
        System.out.println(wr.get()); //这时候会输出null
        System.out.println(rq.poll()); //rq队列里也会存放这个弱引用,输出它的hashcode
    }
}

posted @ 2020-09-04 09:49  gaoyang666  阅读(131)  评论(0编辑  收藏  举报