美文网首页Java基础
Java——软引用、弱引用应用

Java——软引用、弱引用应用

作者: 黄金矿工00七 | 来源:发表于2018-07-31 04:47 被阅读34次
软引用(Soft Reference)

表示一个对象处在有用但非必须的状态。如果一个对象只具有软引用,在内存空间充足时,GC就不会回收该对象;当内存空间不足时,GC会回收该对象的内存(回收发生在OutOfMemoryError之前)。

public static void main(String[] args) {
         
        SoftReference<Cache > sr = new SoftReference<Cache >(new Cache ());
        System.out.println(sr.get());
    }

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被GC回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中,以便在恰当的时候将该软引用回收。但是由于GC线程的优先级较低,通常手动调用System.gc()并不能立即执行GC,因此弱引用所引用的对象并不一定会被马上回收。

弱引用(Weak Reference)

用来描述非必须的对象。它类似软引用,但是强度比软引用更弱一些:弱引用具有更短的生命.GC在扫描的过程中,一旦发现具有被弱引用关联的对象,都会回收掉被弱引用关联的对象。换言之,无论当前内存是否紧缺,GC都将回收被弱引用关联的对象。

 WeakReference<Cache > wr = new WeakReference<Cache >(new Cache ());

同样弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被GC回收了,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中,以便在恰当的时候将该弱引用回收。

ReferenceQueue
/**
 * Reference queues, to which registered reference objects are appended by the
 * garbage collector after the appropriate reachability changes are detected.
 */
  • 引用队列,在检测到适当的可到达性更改后,垃圾回收器将已注册的引用对象添加到该队列中。但实际内部并非有实际的存储结构,它的存储是依赖于内部节点之间的关系来表达。可以理解为queue是一个类似于链表的结构,这里的节点其实就是reference本身。可以理解为queue为一个链表的容器,其自己仅存储当前的head节点,而后面的节点由每个reference节点自己通过next来保持即可。
  • queue的意义在于,我们可以在外部对这个queue进行监控。即如果有对象即将被回收,那么相应的reference对象就会被放到这个queue里。我们拿到reference,就可以再作一些事务。
    而如果不使用的话,就只有不断地轮询reference对象,通过判断里面的get是否返回null( phantomReference对象不能这样作,其get始终返回null,因此它只有带queue的构造函数 )。这两种方法均有相应的使用场景,取决于实际的应用。如weakHashMap中就选择去查询queue的数据,来判定是否有对象将被回收。而ThreadLocalMap,则采用判断get()是否为null来作处理。
  • 如果我们在创建一个引用对象时,指定了ReferenceQueue,那么当引用对象指向的对象达到合适的状态(根据引用类型不同而不同)时,GC 会把引用对象本身添加到这个队列中,方便我们处理它,因为“引用对象指向的对象 GC 会自动清理,但是引用对象本身也是对象(是对象就占用一定资源),所以需要我们自己清理。”


    image.png
ReferenceQueue< Cache > rq=new ReferenceQueue();
WakeReference <Cache>wr=new WakeReference(new Cache (),rq);

需要注意的是如果是显示声明的对象,如下图所示,如果不置为null,那么永远存在一个指向该对象的强引用,如下图,将不会对该对象进行回收

  Cache cache = new Cache();
    ReferenceQueue<Cache> referenceQueue = new ReferenceQueue();
    WeakReference wr = new WeakReference(cache, referenceQueue);
    //cache = null;
    System.gc();
image.png

所以显示声明一个需要软引用或者弱引用的对象时,要设置为null,取消对他的强引用,才会在GC时回收

ReferenceQueue< Cache > rq=new ReferenceQueue();
Cache cache = new Cache ();
WakeReference wr=new WakeReference(cache ,rq);
cache = null;
System.gc();
应用场景

两者都可以实现缓存功能,但软引用实现的缓存通常用在服务端,而在移动设备中的内存更为紧缺,对垃圾回收更为敏感,因此android中的缓存通常是用弱引用来实现(比如LruCache)

相关文章

网友评论

    本文标题:Java——软引用、弱引用应用

    本文链接:https://www.haomeiwen.com/subject/affcvftx.html