Java引用之强引用、软引用、弱引用、幻象引用区别以及使用示例

Java对象引用除了强引用之外还有软引用、弱引用、幻象引用以及FinalReference.

 

强引用:常见的普通对象引用 比如 

Result counter = new Result("Johnny","12");

软引用:能豁免垃圾回收,只有在抛出OOM之前才会清理.

弱引用:不能豁免垃圾回收.用来构建没有特定约束的关系,是很多缓存实现的选择.

幻象引用:在对象被finalize之后的一种引用,不可达调用get()返回null.

FinalReference:处理native的对象,参考FinalReference详解

 

强弱关系:

强引用>软引用>弱引用>幻象引用

 

构造方式两种:

分为不带队列和带队列

Reference(T referent) {
     this(referent, null);
}

Reference(T referent, ReferenceQueue<? super T> queue) {
     this.referent = referent;
     this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}

通用方式:

Object obj = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
XXXXReference<Object> p = new XXXXReference<>(counter, refQueue);

然后是调用方法

p.get()获取对象obj.

p.clear()把对象置为空.

p.isEnqueued()是否入队.

p.enqueue()是否出队

refQueue.remove(1000L)等待1秒后删除

 

用法示例:

SoftReference:GC后对象还在

package com.rongsoft.concurrent.phantomreference;

import lombok.extern.slf4j.Slf4j;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.concurrent.TimeUnit;

@Slf4j
public class SoftReferenceDemo {
    public static void main(String[] args) {
        Result counter = new Result("Johnny","12");
        ReferenceQueue refQueue = new ReferenceQueue<>();
        SoftReference<Object> p = new SoftReference<>(counter, refQueue);
        try {
            //SoftReference可达
            System.out.println("SoftReference.get():"+p.get());
            counter = null;
            System.out.println("counter = null后:"+p.get());
            System.gc();
            System.out.println("System.gc()后:"+p.get());
            // Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
            Reference<Object> ref = refQueue.remove(1000L);
            log.info("SoftReference,remove前---不为空");
            TimeUnit.SECONDS.sleep(1);
            if (ref != null) {
                // do something
                log.info("remove()后,SoftReference不为空");
            }else{
                log.info("remove()后,SoftReference为空");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 输出:

SoftReference.get():Result{name='Johnny', age='12'}
counter = null后:Result{name='Johnny', age='12'}
System.gc()后:Result{name='Johnny', age='12'}
15:17:35.979 [main] INFO com.rongsoft.concurrent.phantomreference.SoftReferenceDemo - SoftReference,remove前---不为空
15:17:36.982 [main] INFO com.rongsoft.concurrent.phantomreference.SoftReferenceDemo - remove()后,SoftReference为空

 弱引用WeakReference:GC后对象不存在了

package com.rongsoft.concurrent.phantomreference;

import lombok.extern.slf4j.Slf4j;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;

@Slf4j
public class WeakReferenceDemo {
    public static void main(String[] args) {
        Result counter = new Result("Johnny","12");
        ReferenceQueue refQueue = new ReferenceQueue<>();
        WeakReference<Object> p = new WeakReference<>(counter, refQueue);
        try {
            System.out.println("WeakReference.get():"+p.get());
            counter = null;
            System.out.println("counter = null后:"+p.get());
            System.gc();
            System.out.println("System.gc()后:"+p.get());
            // Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
            Reference<Object> ref = refQueue.remove(1000L);
            log.info("WeakReference,remove前---不为空");
            TimeUnit.SECONDS.sleep(1);
            if (ref != null) {
                // do something
                log.info("remove()后,WeakReference不为空");
            }else{
                log.info("remove()后,WeakReference为空");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出结果: 

WeakReference.get():Result{name='Johnny', age='12'}
counter = null后:Result{name='Johnny', age='12'}
System.gc()后:null
15:29:06.431 [main] INFO com.rongsoft.concurrent.phantomreference.WeakReferenceDemo - WeakReference,remove前---不为空
15:29:07.435 [main] INFO com.rongsoft.concurrent.phantomreference.WeakReferenceDemo - remove()后,WeakReference不为空

幻象引用PhantomReference:对象一直不可达

package com.rongsoft.concurrent.phantomreference;

import lombok.extern.slf4j.Slf4j;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.TimeUnit;

@Slf4j
public class PhantomReferenceDemo {
    public static void main(String[] args) {
        Result counter = new Result("Johnny","23");
        ReferenceQueue refQueue = new ReferenceQueue<>();
        PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
        try {
            //PhantomReference不可达,所以恒为空
            System.out.println("PhantomReference.get():"+p.get());
            counter = null;
            System.out.println("counter = null后:"+p.get());
            System.gc();
            System.out.println("System.gc()后:"+p.get());
            // Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
            Reference<Object> ref = refQueue.remove(1000L);
            log.info("PhantomReference,remove前---不为空");
            TimeUnit.SECONDS.sleep(1);
            if (ref != null) {
                // do something
                log.info("remove()后,PhantomReference不为空");
            }else{
                log.info("remove()后,PhantomReference为空");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出结果:

PhantomReference.get():null
counter = null后:null
System.gc()后:null
15:38:30.992 [main] INFO com.rongsoft.concurrent.phantomreference.PhantomReferenceDemo - PhantomReference,remove前---不为空
15:38:31.995 [main] INFO com.rongsoft.concurrent.phantomreference.PhantomReferenceDemo - remove()后,PhantomReference不为空

 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞翔的咩咩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值