当前位置: 首页 > Thinking in Java > 正文

第17章 – 深入研究容器 – 持有引用(软引用,弱引用,虚引用)

详情见代码注释

package holding;

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

public class TestReference
{
  public static void main(String[] args)
  {
    ReferenceQueue rQueue = new ReferenceQueue();
    //引用队列
    
    VeryBig softObj = new VeryBig("soft");
    //创建一个软引用对象 中 引用的对象,softObj 是强引用,强引用了这个new VeryBig("soft")
    
    SoftReference softReference = new SoftReference(softObj,rQueue); 
    //创建软引用对象
    
    //软引用中引用的对象只有在内存不足时才会回收(在抛出OutOfMemory之前).
    
    //回收之前,软引用中的对象是软可到达的(即,没有强引用指向new VeryBig("soft"),通过下面的softObj = null;实现)
    //并且,softObj只有softReference与之关联了,这样softObj就是软可到达的.
    
    //软可到达的对象,在系统正常(不存在OutOfMemroy这种情况)时,可以调用softReference.get()方法获取软可到达的对象并且正常使用.
    
    //一旦达到软引用的回收条件后(系统快要OutOfMemory了),softReference的get返回null,
    //此时系统并不是立刻回收软引用中引用的对象,而是,先将该软引用对象本身被放入引用队列中.
    //(当软引用的get方法返回null之后,这个软引用对象本身 立刻被 放入ReferenceQueue中)
    
    //然后系统做了两件事情:(1)调用软引用 中引用对象的finalization过程 (2)真正的回收垃圾.
    //也就是说,get方法返回null时,软引用中的对象还没有被立即回收.
    
    Reference<? extends VeryBig> inq = rQueue.poll(); 
    //检查队列中是否存在立即可用对象,如果存在则将该对象从队列中移除,并立即返回该对象
    
    if(! (null == inq) )
    {
      System.out.println("已经进入ReferenceQueue"); 
      //这里不会执行,因为现在软引用没有放入ReferenceQueue中
    }
    
    softObj = null;
    System.gc(); 
    //这里一般不会回收软引用指向的对象,因为系统对内存还充足,不足以抛出OutOfMemory异常
    
    inq = rQueue.poll();
    if(! (null == inq) )
    {
      System.out.println("SoftReference 已经进入ReferenceQueue");
      //这里也不会执行,因为现在软引用没有放入ReferenceQueue中
    }
    
    /**********************************分隔符********************************************/
    VeryBig weakObj = new VeryBig("weak");
    WeakReference weakReference = new WeakReference(weakObj,rQueue);
    //弱引用对象给软引用类似,但是,只要系统调用垃圾回收,弱可到达的对象立刻被回收.
    
    //然后弱引用对象的get方法返回null.
    //然后,这个软引用对象本身被放入ReferenceQueue中.
    
    //(弱可到达的是指,没有强引用指向weakObj(这里通过weakObj = null实现),
    //weakObj只与weakReference关联)
    //可以理解为,当调用System.gc()之后,这里的弱可到达的weakObj
    //即将被回收,此时弱引用对象本身被放入ReferenceQueue中,
    //然后,系统做了两件事,(1)调用弱引用 中引用对象的finalization过程 (2)真正的回收垃圾.
    
    //需要注意的时,调用finalization过程和真正的回收垃圾发生时间不确定,甚至有时候并不发生.
    
    inq = rQueue.poll();
    if(! (null == inq) )
    {
      System.out.println("weakReference 已经进入ReferenceQueue");
    }
    
    weakObj = null;
    System.gc();
    
    inq = rQueue.poll();
    if(! (null == inq) )
    {
      System.out.println("weakReference 已经进入ReferenceQueue");
    }
    
    /**********************************分隔符********************************************/
    //而 虚引用PhantomReference 只有当 Java 垃圾回收器对其所指向的对象真正进行回收时, 
    //会将其加入到这个 ReferenceQueue 对象中,这样就可以追综对象的销毁情况(具体是什么时候销毁的) 
    //同时,虚引用的get()方法总是返回null.
    //虚引用的例子参考:http://jackyin5918.iteye.com/blog/1882292 最后
    
  }
}

class VeryBig
{
  private static final int SIZE = 10000;
  private long[]           la   = new long[SIZE];
  private String           ident;

  public VeryBig(String id)
  {
    ident = id;
  }

  public String toString()
  {
    return ident;
  }

  protected void finalize()
  {
    System.out.println("Finalizing " + ident);
  }
}

 

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2114.html | 边城网事

该日志由 边城网事 于2015年03月18日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第17章 – 深入研究容器 – 持有引用(软引用,弱引用,虚引用) | 边城网事

第17章 – 深入研究容器 – 持有引用(软引用,弱引用,虚引用) 暂无评论

发表评论

快捷键:Ctrl+Enter