强引用、软引用、弱引用、虚引用分别是什么

强引用(默认支持的默认)

强引用就是我们常见的普通对象引用

    /**
     * 强引用
     */
    private Object strongReference= new Object();

只要还有一个强引用指向一个对象,就表明对象“活着”

当内存不足 的时候,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死也不收
强引用是造成内存泄漏的主要原因

软引用

软引用需要通过Jdk提供的 java.lang.ref.SoftReference实现

    /**
     * 软引用案例
     */
    private static void softReference () {
        Object object = new Object();
        //通过SoftReference软引用对象
        //当开始垃圾回收时,内存充足object不会被回收,内存不足,object被回收
        SoftReference< Object > objectSoftReference = new SoftReference<>(object);

    }

对于软引用的对象来说
1、当系统内存充足时它 不会 被回收
2、当系统内存不足时它 会 被回收

在高速缓存中就有软引用

弱引用

弱引用需要通过Jdk提供的 java.lang.ref.WeakReference实现
弱引用的对象,在垃圾回收的时候,无论内存是否充足,都会被垃圾回收

    /**
     * 弱引用案例
     */
    public static void weakReference () {
        Object object = new Object();
        //当开始垃圾回收的时候,无论内存是否充足,弱引用的对象都会被回收
        WeakReference< Object > objectWeakReference = new WeakReference<>(object);
    }

软引用 、弱引用适用场景

图片缓存
假如有一个应用需要读到大量的本地图片:
~ 如果每次读取图片都要从硬盘读取则会严重影响性能
~ 如果一次性全部加载到内存中又有可能造成内存泄漏

这个软引用可以解决这个问题
设计的思路是:用一个HashMap 来保存图片的路径 和 相应图片对象 关联的软引用 之间的映射关系
内存不足时,JVM会自动回收这些缓存图片所占用的空间,避免OOM

下面我自己写了个缓存类的模板( 要看具体的业务需求 还可以使用WeakHashMap,SoftHashMap)


package com.demo.pojo;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Supplier;


/**
 * 缓存类
 */
public class CacheUtils {
    private static volatile CacheUtils instance;

    private static Map< Object, Object > cacheMap;

    private CacheUtils () {

    }

    /**
     * 根据业务不同,选择构造不同的map 如WeakHashMap ,SoftHashMap 或者其他自定义
     *
     * @param supplier
     */
    public static Map< Object, Object > getCacheMap (Supplier< Map > supplier) {
        if (cacheMap == null) {
            synchronized (CacheUtils.class) {
                if (cacheMap == null) {
                    cacheMap = supplier.get();
                }
            }
        }
        return cacheMap;
    }


    /**
     * 通过静态内部类实现单例
     */
    private static class CacheUtilsInstance {
        private static final CacheUtils INSTANCE = new CacheUtils();
    }

    public static CacheUtils getInstance () {
        return CacheUtilsInstance.INSTANCE;
    }

    public static void main (String[] args) {
    	//根据业务需求,去创建对应的缓存map
        Map< Object, Object > cacheMap = CacheUtils.getInstance().getCacheMap(() -> {
            return new WeakHashMap();
        });
    }

}

知道弱引用,那聊聊WeakHashMap

WeakHashMap就是Map的一种,底层就是将kv 用WeakReference 包装起来 ,还有和引用队列ReferenceQueue结合使用(引用队列下面 会进行介绍)

下面是它的结点的代码

 /**
     * The entries in this hash table extend WeakReference, using its main ref
     * field as the key.
     */
    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
        V value;
        final int hash;
        Entry<K,V> next;

        /**
         * Creates new entry.
         */
        Entry(Object key, V value,
              ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }

虚引用

一、引用队列

了解虚引用之前,必须要了解引用队列, 虚引用需要和引用队列搭配使用

在这里插入图片描述
如果用了引用队列,对象在被回收前需要被引用队列保存下

public class ReferenceQueueDemo {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);

        System.out.println(o1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("--------------------------");
        o1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(o1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());
    }
}(内存不够时)、弱、虚引用,gc后放到引用队列中
 
java.lang.Object@1540e19d
java.lang.Object@1540e19d
null
--------------------------
null
null
java.lang.ref.WeakReference@677327b6
二、虚引用

虚引用需要 java.lang.ref.PhantomReference 来实现

顾名思义,他形同虚设,虚引用不会决定对象的生命周期

如果一个对象一个对象仅持有虚引用,在任何时候都有可能被垃圾回收器回收,而且他必须和引用队列ReferenceQueue搭配使用
在这里插入图片描述

public class PhantomReferenceDemo {

    public static void main(String[] args) {
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        PhantomReference<Object> reference = new PhantomReference<>(o1, referenceQueue);

        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(referenceQueue.poll());

        o1 = null;
        System.gc();
        System.out.println("------------------");
        System.out.println(o1);
        System.out.println(reference.get());
        System.out.println(referenceQueue.poll());
    }
}
 
java.lang.Object@1540e19d
null
null
------------------
null
null
java.lang.ref.PhantomReference@677327b6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值