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);
        }
    
    }
    
  • 相关阅读:
    金蝶问题:不能保存已审核的单据
    在代码中设置cxTreeList按多列排序
    日积月累篇:生产任务单
    sp_reset_connection
    日积月累篇:仓库流程
    使用FreeMarker生成Word文档 仅此而已
    ASP格式化时间日期(二)
    省市区三级联动连接数据库
    利用SQL语句进行添加、删除、修改字段,表与字段的基本操作,数据库备份等
    ASP截取字数(二)
  • 原文地址:https://www.cnblogs.com/jamesvoid/p/10127339.html
Copyright © 2011-2022 走看看