美文网首页
ReferenceQueue的处理

ReferenceQueue的处理

作者: XJ2017 | 来源:发表于2018-01-31 10:35 被阅读0次

    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];
    }

    相关文章

      网友评论

          本文标题:ReferenceQueue的处理

          本文链接:https://www.haomeiwen.com/subject/csrkzxtx.html