java.lang.ref.Reference类中有静态块启动线程(java.lang.ref.Reference.ReferenceHandler)
static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
}
线程死循环去java.lang.ref.Reference.pending的值(等待队列的列表引用。收集器将引用添加到此列表)
/* List of References waiting to be enqueued. The collector adds
* References to this list, while the Reference-handler thread removes
* them. This list is protected by the above lock object.
*/
private static Reference pending = null;
/* High-priority thread to enqueue pending References
*/
private static class ReferenceHandler extends Thread {
ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
public void run() {
for (;;) {
Reference r;
synchronized (lock) {
if (pending != null) {
r = pending;
Reference rn = r.next;
pending = (rn == r) ? null : rn;
r.next = r;
} else {
try {
lock.wait();
} catch (InterruptedException x) { }
continue;
}
}
// Fast path for cleaners
if (r instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
ReferenceQueue q = r.queue;
if (q != ReferenceQueue.NULL) q.enqueue(r);
}
}
}
如果有则丢进队列(java.lang.ref.ReferenceQueue),应用代码调用java.lang.ref.ReferenceQueue.poll()获取引用对象进行处理
/**
* 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();
}
}
private Reference<? extends T> reallyPoll() { /* Must hold lock */
if (head != null) {
Reference<? extends T> r = head;
head = (r.next == r) ? null : r.next;
r.queue = NULL;
r.next = r;
queueLength--;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(-1);
}
return r;
}
return null;
}
使用案例
/**
* 作者:赵北云
* 链接:https://www.zhihu.com/question/35250439/answer/62942987
* 来源:知乎
* 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class ReferenceQueueExample {
public static void main(String[] args) {// -Xmx32m
List<FooWeakReference> list = new ArrayList<>();
// 这个没有加队列 所以会爆
// for (int i = 0; i < 32 * 1024; i++) {
// list.add(new FooWeakReference(i));
// }
// 这个加咧 所以不会爆
ReferenceQueue<Integer> queue = new ReferenceQueue<>();
FooWeakReference ref = null;
for (int i = 0; i < 32 * 1024; i++) {
list.add(new FooWeakReference(i, queue));
System.out.println(i + ";begin");
while ((ref = (FooWeakReference) queue.poll()) != null) {
ref.clean();
System.out.println(i + ";ref.clean()");
}
System.out.println(i + ";end");
}
}
}
class FooWeakReference extends WeakReference<Integer> {
public FooWeakReference(Integer referent) {
super(referent);
}
public FooWeakReference(Integer referent, ReferenceQueue<Integer> q) {
super(referent, q);
}
public void clean() {
this.buffer = null;
}
byte[] buffer = new byte[1024];
}