这个方法主要完成了discovered -> pending -> enqueued的整个入队注册流程;值得注意的是虽然Cleaner是虚引用,但是它并不会入队,而是直接执行clean操作,也就意味着在使用Cleaner的时候不需要在起一个线程监听ReferenceQueue了;
4. ReferenceQueue 概览 static ReferenceQueue<Object> NULL = new Null<>(); // 用于标记是否已经入队,防止重复入队 static ReferenceQueue<Object> ENQUEUED = new Null<>(); private volatile Reference<? extends T> head = null; private long queueLength = 0; // reference入队操作 boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */ // poll 移除reference链表头元素 public Reference<? extends T> poll() { } // 移除reference链表下一个元素 public Reference<? extends T> remove(long timeout) { } public Reference<? extends T> remove() throws InterruptedException { } void forEach(Consumer<? super Reference<? extends T>> action) { }从上面的代码也可以看出ReferenceQueue的确没有包含任何链表或者队列的结构,但是封装了单向的链表的操作;
总结Reference 主要用于更加灵活的控制对象的生死,其实现类似于事件处理,可以是 JVM 默认处理,也可以是用户自定义的处理逻辑;
在 Java 语言中 Reference 类定义了子类(SoftReference,WeakReference,PhantomReference)主要的逻辑,并且判断引用回收的条件主要在 JVM 中定义;
如果在使用 Reference 的时候传入了 ReferenceQueue,即使用自定义的逻辑处理,那么最后一定要把 ReferenceQueue 中注册的 Reference 移除,因为此时 GC 不会回收 ReferenceQueue 中的链表;