Java Reference 源码分析(2)

// 用于标识没有注册Queue static ReferenceQueue NULL = new Null(); // 用于标识已经处于对应的Queue中 static ReferenceQueue ENQUEUED = new Null(); static private class Lock { }; /* 互斥锁,用于同步ReferenceHandler的enqueue和用户线程操作的remove和poll出队操作 */ private Lock lock = new Lock(); // 队列 private volatile Reference<? extends T> head = null; // 队列中的元素个数 private long queueLength = 0;

ReferenceQueue.enqueue

只会通过Reference里要调用该方法,用于将Reference放入到当前队列中

booleanenqueue(Reference<? extends T> r) { synchronized (r) { // 判断是否已经入队了 if (r.queue == ENQUEUED) return false; synchronized (lock) { r.queue = ENQUEUED; // 单向循环 r.next = (head == null) ? r : head; head = r; queueLength++; if (r instanceof FinalReference) { sun.misc.VM.addFinalRefCount(1); } // 通知当前挂起的线程(调用remove时有可能会挂起) lock.notifyAll(); return true; } } }

ReferenceQueue.remove

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; for (;;) { // 否则等待,由enqueue时notify唤醒 lock.wait(timeout); r = reallyPoll(); if (r != null) return r; if (timeout != 0) return null; } } }

具体执行流程

以上述示例Demo1作为分析

// 创建一个引用队列 ReferenceQueue queue = new ReferenceQueue(); // 创建虚引用,此时状态为Active,并且Reference.pending为空,当前Reference.queue = 上面创建的queue,并且next=null WeakReference reference = new WeakReference(new Object(), queue); System.out.println(reference); // 当GC执行后,由于是虚引用,所以回收该object对象,并且置于pending上,此时reference的状态为PENDING System.gc(); /* ReferenceHandler从pending中取下该元素,并且将该元素放入到queue中,此时Reference状态为ENQUEUED,Reference.queue = ReferenceENQUEUED */ /* 当从queue里面取出该元素,则变为INACTIVE,Reference.queue = Reference.NULL */ Reference reference1 = queue.remove(); System.out.println(reference1);

应用 - WeakHashMap

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c584ef90782641d1352d698ad34ad7e9.html