JAVA中输出姓王的姓名_java Reference

这篇博客详细解释了JAVA中的Reference类及其子类,包括SoftReference、WeakReference和PhantomReference,它们在垃圾回收过程中的作用以及如何与ReferenceQueue配合工作。重点介绍了Reference对象的四种状态,并分析了如何影响对象的可达性和回收策略。
摘要由CSDN通过智能技术生成

相关讲解,参考:

Reference:

// 名称说明下:Reference指代引用对象本身,Referent指代被引用对象

/**

* Reference的抽象基类,这个类中定义了所有引用对象的常用操作。

* 由于引用对象是通过与垃圾回收器密切合作来实现的,因此,不要直接继承此基类;

*

* @since 1.2

*/

public abstract class Reference {

/*

* 一个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 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 {

public ReferenceQueue() {

}

private static class Null extends ReferenceQueue {

boolean enqueue(Reference extends S> r) {

return false;

}

}

// 当我们构造Reference实例时queue传入null时,会默认使用NULL

static ReferenceQueue NULL = new Null<>();

// 防止重复入队,reference入队后会把其queue字段赋值为ENQUEUED,当再次入队时会直接返回失败。

static ReferenceQueue 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 extends Reference {

// 由虚拟机更新该时间戳

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 extends Reference {

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 extends Reference {

// 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);

}

}

Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值