欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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 源码分析
相关标签: ReferenceQueue