Guava---缓存之Reference


在 jdk 1.2 及其以后,引入了强引用、软引用、弱引用、虚引用这四个概念。网上很多关于这四个概念的解释,但大多是概念性的泛泛而谈,今天我结合着代码分析了一下,首先我们先来看定义与大概解释(引用类型在包 java.lang.ref 里)。强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference),虚引用(PhantomReference).
为了掩饰下面例子,将JVM堆内存设置为64M.

强引用(StrongReference)

强引用不会被GC回收,并且在java.lang.ref里也没有实际的对应类型。举个例子来说:
    Object obj = new Object();
    这里的obj引用便是一个强引用,不会被GC回收。

/**
 * @Description:  强引用
 *
 * 设置堆最大内存128M,超出将OutOfMemoryError
 * @Date: 2018/11/12 0:01
 */
public class StrongReference {

    public static void main(String[] args) {
        int i =0;
        List<Ref> list = new ArrayList<>();
        for (;;){
            int i1 = i++;
            Ref ref = new Ref(i1);
            list.add(ref);
            System.out.println(i1 + "加到list中");
        }

    }

    private static class Ref{
        private byte[] bytes = new byte[1024*1024];//1M
        private final int index;

        private Ref(int index) {
            this.index = index;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("--index---" + index + "---将要GC");
        }
    }
}

当堆内存满时,将OutOfMemoryError.

软引用(SoftReference)

软引用在JVM报告内存不足的时候才会被GC回收,否则不会回收,正是由于这种特性软引用在caching和pooling中用处广泛。软引用的用法:

Object obj = new Object();
SoftReference<Object> softRef = new SoftReference(obj);
// 使用 softRef.get() 获取软引用所引用的对象
Object objg = softRef.get();
/**
 *SoftReference(软引用):
 * 当发生GC(MinorGC/FullGC)时,当检测到JVM内存快要满了,将GC Soft Reference
 * <P>
 *     SoftReference可能会OutOfMemoryError
 *     1.当我们把睡眠时间调制1ms时,会报OutOfMemoryError
 *     2.当我们把睡眠时间调制1s时,程序会一直执行下去,可以看到对象被GC
 *     分析:时间调至1ms,这时还未来得及GC,又放入,会出现堆内存溢出
 *          当1s时,有足够的时间去GC.不会全部GC掉
 *     总结:在缓存中,一般放的次数远远小于放的次数,不可能不断地放入缓存,因此用SoftReference,绝大多时候
 *     不会报OutOfMemoryError
 *
 * <P/>
 */
public class Soft_Reference {

    public static void main(String[] args) throws InterruptedException {
        int i =0;
        List<SoftReference<Ref>> list = new ArrayList<>();
        for (;;){
            int i1 = i++;
            list.add(new SoftReference<>(new Ref(i1)));
            System.out.println(i1 + "加到list中");
            TimeUnit.MILLISECONDS.sleep(1000);
        }

    }

    private static class Ref{
        private byte[] bytes = new byte[1024*1024];//1M
        private final int index;

        private Ref(int index) {
            this.index = index;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("--index---" + index + "---将要GC");
        }
    }
}

弱引用(WeakReference)

当GC一但发现了弱引用对象,将会释放WeakReference所引用的对象

/**
 *WeakReference(弱引用):
 * 当发生GC(MinorGC/FullGC)时,都会被回收掉。
 */
public class Weak_Reference {

    public static void main(String[] args) throws InterruptedException {
        int i =0;
        List<WeakReference<Ref>> list = new ArrayList<>();
        for (;;){
            int i1 = i++;
            list.add(new WeakReference<>(new Ref(i1)));
            System.out.println(i1 + "加到list中");


            TimeUnit.MILLISECONDS.sleep(100);
        }

    }

    private static class Ref{
        private byte[] bytes = new byte[1024*1024];//1M
        private final int index;

        private Ref(int index) {
            this.index = index;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("--index---" + index + "---将要GC");
        }
    }
}

虚引用(PhantomReference).

当GC一但发现了虚引用对象,将会将PhantomReference对象插入ReferenceQueue队列,而此时PhantomReference所指向的对象并没有被GC回收,而是要等到ReferenceQueue被你真正的处理后才会被回收。虚引用的用法:

Object obj = new Object();
ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue);
// 调用phanRef.get()不管在什么情况下会一直返回null
Object objg = phanRef.get();
// 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列
// 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后
// 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收
Reference<? extends Object> phanRefP = refQueue.poll();

虚引用在实现一个对象被回收之前必须做清理操作是很有用的。有时候,他们比finalize()方法更灵活。

很明显的,虚引用可以用来做对象被回收之前的清理工作。
//TODO
对于Reference先介绍到这,能力有限,后面再继续补充.

参考:https://blog.csdn.net/aitangyong/article/details/39453365

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值