ReferenceQueue 博客分类: java.lang.ref ReferenceQueue
程序员文章站
2024-02-05 17:54:28
...
ReferenceQueue
一、总结
1.jkd 1.8.0
2.作用
该队列作为引用中的一员,可以和上述三种引用类型组合使用,该队列的作用是:创建Reference时,将Queue注册到Reference中,当该Reference所引用的对象被垃圾收集器回收时,会将该Reference放到该队列中,相当于一种通知机制。
二、源码分析
/** * Reference queues, to which registered reference objects are appended by the * garbage collector after the appropriate reachability changes are detected. * * @author Mark Reinhold * @since 1.2 */ public class ReferenceQueue<T> { }
- Reference queues,在适当的时候检测到对象的可达性发生改变后,垃圾回收器就将已注册的引用对象添加到此队列中。
/** * Constructs a new reference-object queue. */ public ReferenceQueue() { }
- 构造方法,需指定泛型
// 私有内部静态类 Null ,继承 ReferenceQueue ,并覆盖实现父类中的方法 enqueue private static class Null<S> extends ReferenceQueue<S> { boolean enqueue(Reference<? extends S> r) { return false; } } // Reference 对象出队列标识,即 Reference 状态,由 Enqueued 变为 Inactive static ReferenceQueue<Object> NULL = new Null<>(); // Reference 对象入队列标识,即 Reference 状态,由 Pending 变为 Enqueued static ReferenceQueue<Object> ENQUEUED = new Null<>();
- 出队、入队标识,队列指的是 Reference 构造方法中 ReferenceQueue 参数
static private class Lock { }; private Lock lock = new Lock();
- 锁:类对象锁
private volatile Reference<? extends T> head = null;
- 列表头部
- 作用:出队、入队操作时,作为临时变量保存数据
private long queueLength = 0;
- 队列中元素的个数
- 类中的属性,实例对象私有,Reference 构造方法需要传入 ReferenceQueue 的实例对象,此属性指的是传入对象的队列中的对象的数量
boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */ synchronized (lock) { // Check that since getting the lock this reference hasn't already been // enqueued (and even then removed) ReferenceQueue<?> queue = r.queue; // 检查需要入队的 Reference 对象,对象的 queue 属性是否已经有标识 // 即已经做过入队、出队的处理 if ((queue == NULL) || (queue == ENQUEUED)) { return false; } // 断言 assert queue == this; // 入队处理,入队标识 r.queue = ENQUEUED; // 新入队对象放在头部 r.next = (head == null) ? r : head; head = r; queueLength++; // 如果是强引用对象 if (r instanceof FinalReference) { sun.misc.VM.addFinalRefCount(1); } lock.notifyAll(); // 释放锁对象 return true; } }
- 添加入队标识
- 新加入的元素在队列头部
@SuppressWarnings("unchecked") private Reference<? extends T> reallyPoll() { /* Must hold lock */ Reference<? extends T> r = head; if (r != null) { // r.next == r 仅有一个元素 head = (r.next == r) ? null : r.next; // Unchecked due to the next field having a raw type in Reference r.queue = NULL; // 出队元素的next 指向自己 r.next = r; queueLength--; if (r instanceof FinalReference) { sun.misc.VM.addFinalRefCount(-1); } return r; } return null; } /** * Polls this queue to see if a reference object is available. If one is * available without further delay then it is removed from the queue and * returned. Otherwise this method immediately returns <tt>null</tt>. * * @return A reference object, if one was immediately available, * otherwise <code>null</code> */ public Reference<? extends T> poll() { if (head == null) return null; synchronized (lock) { return reallyPoll(); } }
- 添加出队标识
- 从头部开始出队,先入后出
/** * Removes the next reference object in this queue, blocking until either * one becomes available or the given timeout period expires. * * <p> This method does not offer real-time guarantees: It schedules the * timeout as if by invoking the {@link Object#wait(long)} method. * * @param timeout If positive, block for up to <code>timeout</code> * milliseconds while waiting for a reference to be * added to this queue. If zero, block indefinitely. * * @return A reference object, if one was available within the specified * timeout period, otherwise <code>null</code> * * @throws IllegalArgumentException * If the value of the timeout argument is negative * * @throws InterruptedException * If the timeout wait is interrupted */ public Reference<? extends T> remove(long timeout) throws IllegalArgumentException, InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("Negative timeout value"); } synchronized (lock) { Reference<? extends T> r = reallyPoll(); if (r != null) return r; long start = (timeout == 0) ? 0 : System.nanoTime(); for (;;) { lock.wait(timeout); r = reallyPoll(); if (r != null) return r; if (timeout != 0) { long end = System.nanoTime(); timeout -= (end - start) / 1000_000; if (timeout <= 0) return null; start = end; } } } } /** * Removes the next reference object in this queue, blocking until one * becomes available. * * @return A reference object, blocking until one becomes available * @throws InterruptedException If the wait is interrupted */ public Reference<? extends T> remove() throws InterruptedException { return remove(0); } }
- 删除队列中的下一个引用对象,阻塞队列直到一个引用对象变为可达
博文参考:
Java Reference 源码分析