Guava---缓存之Reference

文章目录

    • 强引用(StrongReference)
    • 软引用(SoftReference)
    • 弱引用(WeakReference)
    • 虚引用(PhantomReference).

在 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 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 softRef = new SoftReference(obj);
// 使用 softRef.get() 获取软引用所引用的对象
Object objg = softRef.get();
 
  
/**
 *SoftReference(软引用):
 * 当发生GC(MinorGC/FullGC)时,当检测到JVM内存快要满了,将GC Soft Reference
 * 

* SoftReference可能会OutOfMemoryError * 1.当我们把睡眠时间调制1ms时,会报OutOfMemoryError * 2.当我们把睡眠时间调制1s时,程序会一直执行下去,可以看到对象被GC * 分析:时间调至1ms,这时还未来得及GC,又放入,会出现堆内存溢出 * 当1s时,有足够的时间去GC.不会全部GC掉 * 总结:在缓存中,一般放的次数远远小于放的次数,不可能不断地放入缓存,因此用SoftReference,绝大多时候 * 不会报OutOfMemoryError * *

*/ public class Soft_Reference { public static void main(String[] args) throws InterruptedException { int i =0; List> 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> 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 refQueue = new ReferenceQueue();
PhantomReference phanRef = new PhantomReference(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 phanRefP = refQueue.poll();
 
  

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

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

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

你可能感兴趣的:(Guava)