zoukankan      html  css  js  c++  java
  • java Reference

    相关讲解,参考:

    Java Reference 源码分析

    Java Reference详解

    Reference:

    // 名称说明下:Reference指代引用对象本身,Referent指代被引用对象
    /**
     * Reference的抽象基类,这个类中定义了所有引用对象的常用操作。
     * 由于引用对象是通过与垃圾回收器密切合作来实现的,因此,不要直接继承此基类;
     * 
     * @since 1.2
     */
    public abstract class Reference<T> {
    
        /*
         * 一个Reference实例总是处于以下4种状态之一:
         *
         * 1.Active:Active状态的Reference会受到GC的特别关注,当GC察觉到引用的可达性变化为相应的(appropriate)状态
         * 之后,它的状态将变化为Pending或Inactive;
         * 如果该实例在创建时注册了ReferenceQueue,那么变为Pendging状态,并且添加这个实例到pending-Reference list;
         * 否则变为Inactive状态; 新建的Reference对象都为Active状态; 
         * 此时,queue = 创建实例时注册的 ReferenceQueue 或 ReferenceQueue.NULL; next = null;
         * 
         * 2.Pending:在pending-Reference list中时为该状态,等待被Reference-handler 线程添加
         * 其对应的ReferenceQueue中;
         * 此时,queue = 创建实例时注册的 ReferenceQueue; next = queue中的下一个元素 或 自身;
         * 
         * 3.Enqueued:在ReferenceQueue中时为该状态.被从该ReferenceQueue中移除时变为Inactive状态;
         * 此时,queue = ReferenceQueue.ENQUEUED; next = queue中的下一个元素 或 自身;
         *
         * 4.Inactive:一旦一个实例变为Inactive,则这个状态永远都不会再被改变;
         * queue = ReferenceQueue.NULL; next = this.
         */
         // Reference构造方法默认会注册ReferenceQueue.NULL,所有目前不存在从Active直接到Inactive的状态转变
    
    
        // 该reference指向的具体对象
        private T referent; /* Treated specially by GC */
    
        ReferenceQueue<? super T> queue;
    
        Reference next;
        transient private Reference<T> discovered; /* used by VM */
    
        static private class Lock {
        };
    
        private static Lock lock = new Lock();
    
        // 由JVM来赋值的,当Reference内部的referent对象的可达状态发生改变,且注册了ReferenceQueue时,
        // JVM会将Reference对象放入到pending链表中,等待被添加进其对应的ReferenceQueue中;
        // ReferenceHandler 不停从这个里面取 reference,加到对应的 ReferenceQueue 中;
        // 该链表的所有访问都是在获取锁lock的时候
        private static Reference pending = null;
    
        // 高优先级线程,用于将pending链表中的reference添加到其ReferenceQueue队列中
        private static class ReferenceHandler extends Thread {
    
            ReferenceHandler(ThreadGroup g, String name) {
                super(g, name);
            }
    
            public void run() {
                for (;;) {
    
                    Reference r;
                    synchronized (lock) {
                        // pending list中有值,取出来
                        if (pending != null) {
                            r = pending;
                            Reference rn = r.next;
                            // 重置新pending
                            pending = (rn == r) ? null : rn;
                            // 设置next为自身
                            r.next = r;
                        } else {
                            try {
                                // 等待,直到被唤醒
                                lock.wait();
                            } catch (InterruptedException x) {
                            }
                            // 唤醒后,取下一个
                            continue;
                        }
                    }
    
                    // Fast path for cleaners
                    if (r instanceof Cleaner) {
                        ((Cleaner) r).clean();
                        continue;
                    }
                    // 将从 pending list 中取出的reference添加到其对应的ReferenceQueue中
                    ReferenceQueue q = r.queue;
                    if (q != ReferenceQueue.NULL)
                        q.enqueue(r);
                }
            }
        }
    
        // 启动 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");
            handler.setPriority(Thread.MAX_PRIORITY);
            handler.setDaemon(true);
            handler.start();
        }
    
        /* -- Referent accessor and setters -- */
    
        // 返回Reference指向的对象,如果指向的对象被回收,返回null
        public T get() {
            return this.referent;
        }
    
        // 清除对指向的对象的引用;不会将reference添加到队列中;
        // gc回收时会直接将referent置为null,不会调用该方法.
        public void clear() {
            this.referent = null;
        }
    
        /* -- Queue operations -- */
    
        public boolean isEnqueued() {
            synchronized (this) {
                return (this.queue != ReferenceQueue.NULL) && (this.next != null);
            }
        }
    
        public boolean enqueue() {
            return this.queue.enqueue(this);
        }
    
        /* -- Constructors -- */
        Reference(T referent) {
            this(referent, null);
        }
    
        Reference(T referent, ReferenceQueue<? super T> queue) {
            this.referent = referent;
            // 默认队列 ReferenceQueue.NULL
            this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
        }
    
    }
    
    

    ReferenceQueue:

    /**
     * Reference queues,在检测到Reference对象发生了相应的(appropriate)可达性改变后,
     * 垃圾回收器就将已注册的引用对象添加到对应的ReferenceQueue中。
     * 单向队列:但是其更行为是一个栈,LIFO;插入元素时使用头插法,取出元素时取出队列头;
     * 队列的节点为Reference对象;
     * 
     * @since 1.2
     */
    public class ReferenceQueue<T> {
    
        public ReferenceQueue() {
        }
    
        private static class Null<S> extends ReferenceQueue<S> {
            boolean enqueue(Reference<? extends S> r) {
                return false;
            }
        }
    
        // 当我们构造Reference实例时queue传入null时,会默认使用NULL
        static ReferenceQueue<Object> NULL = new Null<>();
        // 防止重复入队,reference入队后会把其queue字段赋值为ENQUEUED,当再次入队时会直接返回失败。
        static ReferenceQueue<Object> ENQUEUED = new Null<>();
    
        static private class Lock {
        };
    
        private Lock lock = new Lock();
        private volatile Reference<? extends T> head = null;
        private long queueLength = 0;
    
        boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
            synchronized (lock) {
                ReferenceQueue<?> queue = r.queue;
                // 判断是否传入的引用没有ReferenceQueue || 已经入队
                if ((queue == NULL) || (queue == ENQUEUED)) {
                    return false;
                }
                assert queue == this;
                // 入队之后,将引用的队列改为ENQUEUED,作为标志位
                // 状态切为ENQUEUED状态
                r.queue = ENQUEUED;
                // 如果队列中只有一个元素,那么这个元素的next指向自身;
                // 头插法;
                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) {
                // 重置新head
                head = (r.next == r) ? null : r.next; // Unchecked due to the next field having a raw type in Reference
                // 状态切为INACTIVE状态
                r.queue = NULL;
                r.next = r;
                queueLength--;
                // FinalReference特殊处理,暂不了解
                if (r instanceof FinalReference) {
                    sun.misc.VM.addFinalRefCount(-1);
                }
                return r;
            }
            return null;
        }
    
        // 如果存在可用的Reference对象,返回该对象;否则返回null;
        public Reference<? extends T> poll() {
            if (head == null)
                return null;
            synchronized (lock) {
                return reallyPoll();
            }
        }
    
        // 阻塞等待提取队列元素
        // 如果指定的timeout没有获取到reference,返回null;
        // 如果timeout为0,无限期等待,知道获取到reference;
        // timeout单位为ms;
        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;
                    }
                }
            }
        }
    
        public Reference<? extends T> remove() throws InterruptedException {
            return remove(0);
        }
    
    }
    

    SoftReference:

    /**
     * SoftReference 指向的对象,在内存不足时会被GC回收; Soft 通常被用于实现
     * 内存敏感(memory-sensitive)的缓存(cache);
     * 在抛出 OOM 之前,虚拟机会保证所有的 softly-reachable 对象被回收;
     * 某些虚拟机可能倾向于不清除(bias against)
     * 最近创建(recently-created)或最近使用过(recently-used)的soft references
     * 指向的对象;
     *
     * @since 1.2
     */
    public class SoftReference<T> extends Reference<T> {
    
        // 由虚拟机更新该时间戳
        static private long clock;
    
        // 调用get()时会更新,虚拟机可能(只是可能)使用这个域
        // 作为选择softreference对象进行清除的依据
        private long timestamp;
    
        public SoftReference(T referent) {
            super(referent);
            this.timestamp = clock;
        }
    
        public SoftReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
            this.timestamp = clock;
        }
    
        public T get() {
            T o = super.get();
            if (o != null && this.timestamp != clock)
                this.timestamp = clock;
            return o;
        }
    
    }
    

    WeakReference:

    /**
     * weakreference 不影响GC回收 其指向的实例;
     * 如果一个对象为 weakly reachable,虚拟机会将到这个对象的所有weakreference添加到其注册的referencequeue中
     * @since    1.2
     */
    public class WeakReference<T> extends Reference<T> {
    
        public WeakReference(T referent) {
            super(referent);
        }
    
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    
    }
    

    PhantomReference:

    /**
     * 指向的referent如果被回收,该PhantomReference将被添加到其指定的ReferenceQueue中
     * Unlike soft and weak references, phantom references are not
     * automatically cleared by the garbage collector as they are enqueued.  An
     * object that is reachable via phantom references will remain so until all
     * such references are cleared or themselves become unreachable.
     * @since    1.2
     */
    // 从文档描述上来看,这个类除了阻止GC正常回收外,没什么用,因为无法获取到指向的对象
    // phantom  /'fæntəm/ :幽灵;幻影;虚位;幽灵的;幻觉的;有名无实的
    // You know it is somewhere,but you never know where
    // 这个引用,是没有灵魂的
    public class PhantomReference<T> extends Reference<T> {
    
        // get()方法永远返回null
        public T get() {
            return null;
        }
    
        // PhantomReference 必须和 ReferenceQueue 一起使用
        // 如果这里的queue也可以传入一个null,这个PhantomReference完全没用(completely useless)
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    
    }
    
  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/jamesvoid/p/10127339.html
Copyright © 2011-2022 走看看