你不可不知的Java引用类型之——ReferenceQueue源码详解

 

定义

ReferenceQueue是引用队列,用于存放待回收的引用对象。

说明

对于软引用、弱引用和虚引用,如果我们希望当一个对象被垃圾回收器回收时能得到通知,进行额外的处理,这时候就需要使用到引用队列了。

在一个对象被垃圾回收器扫描到将要进行回收时,其相应的引用包装类,即reference对象会被放入其注册的引用队列queue中。可以从queue中获取到相应的对象信息,同时进行额外的处理。比如反向操作,数据清理,资源释放等。

使用例子

public class ReferenceQueueTest {     private static ReferenceQueue<byte[]> rq = new ReferenceQueue<>();     private static int _1M = 1024 * 1024;      public static void main(String[] args) {         Object value = new Object();         Map<WeakReference<byte[]>, Object> map = new HashMap<>();         Thread thread = new Thread(ReferenceQueueTest::run);         thread.setDaemon(true);         thread.start();          for(int i = 0;i < 100;i++) {             byte[] bytes = new byte[_1M];             WeakReference<byte[]> weakReference = new WeakReference<>(bytes, rq);             map.put(weakReference, value);         }         System.out.println("map.size->" + map.size());                  int aliveNum = 0;         for (Map.Entry<WeakReference<byte[]>, Object> entry : map.entrySet()){             if (entry != null){                 if (entry.getKey().get() != null){                     aliveNum++;                 }             }         }         System.out.println("100个对象中存活的对象数量:" + aliveNum);     }      private static void run() {         try {             int n = 0;             WeakReference k;             while ((k = (WeakReference) rq.remove()) != null) {                 System.out.println((++n) + "回收了:" + k);             }         } catch (InterruptedException e) {             e.printStackTrace();         }     } }

这里有一个小栗子,main方法中,创建了一条线程,使用死循环来从引用队列中获取元素,监控对象被回收的状态。然后循环往map中添加了100个映射关系,以下是运行结果:

...前面省略了大量相似输出 85回收了:java.lang.ref.WeakReference@7106e68e 86回收了:java.lang.ref.WeakReference@1f17ae12 87回收了:java.lang.ref.WeakReference@c4437c4 map.size->100 100个对象中存活的对象数量:12

通过配合使用ReferenceQueue,可以较好的监控对象的生存状态。

成员变量

ReferenceQueue中内部成员变量也很少,主要有这么几个:

static ReferenceQueue<Object> NULL = new Null<>(); static ReferenceQueue<Object> ENQUEUED = new Null<>();

有两个用来做为特殊标记的静态成员变量,一个是NULL,一个是ENQUEUE,上一篇中说的ReferenceQueue.NULL和ReferenceQueue.ENQUEUED就是这两个家伙。

来看看Null长什么样:

private static 
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信