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);
}
}
java Reference的更多相关文章
- Java Reference简要概述
@(Java)[Reference] Java Reference简要概述 Reference对象封装了其它对象的引用,可以和普通的对象一样操作. Java提供了四种不同类型的引用,引用级别从高到低分 ...
- Java Reference 源码分析
@(Java)[Reference] Java Reference 源码分析 Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使 ...
- Java Reference & ReferenceQueue一览
Overview The java.lang.ref package provides more flexible types of references than are otherwise ava ...
- Java Reference核心原理分析
本文转载自Java Reference核心原理分析 导语 带着问题,看源码针对性会更强一点.印象会更深刻.并且效果也会更好.所以我先卖个关子,提两个问题(没准下次跳槽时就被问到). 我们可以用Byte ...
- Implementing the skip list data structure in java --reference
reference:http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html The link ...
- 理解java reference
Java世界泰山北斗级大作<Thinking In Java>切入Java就提出“Everything is Object”.在Java这个充满Object的世界中,reference是一 ...
- What Influences Method Call Performance in Java?--reference
reference from:https://www.voxxed.com/blog/2015/02/too-fast-too-megamorphic-what-influences-method-c ...
- Why String is immutable in Java ?--reference
String is an immutable class in Java. An immutable class is simply a class whose instances cannot be ...
- java Reference(摘录)
Java中的Reference对象和GC是紧密联系在一起的,Reference的实现也是和GC相关的. 强引用 强引用是Java中使用最普遍的引用,我们经常使用的Object o = new Obje ...
随机推荐
- adb常用命令(转)
1.Android Debug Bridge -adb常用命令 1.1简介 Android Debug Bridge,我们一般简称为adb,主要存放在sdk安装目录下的platform-tools文件 ...
- 【python3】 函数 装饰器
第一步 : 了解装饰器 装饰器模式,重点在于装饰,装饰的核心仍是被装饰的对象. 举一个栗子:我今天穿了一件短袖,但是突然一阵风,短袖没办法为我御寒,我想到的办法是将短袖变得更厚更长,但是改造之后,它就 ...
- Unity外包团队:关于手机unity游戏开发的技术选型
技术选型 Unity引擎内置了多人联机的解决方案,涵盖了从最底层的网络数据传输,到不同玩家之间的消息发送,再到游戏大厅这样的高级功能.考虑到Unity官方提供的云服务(Internet Service ...
- 关于Ocelot和Consul 实现GateWay(网关) 服务注册 负载均衡等方面
Ocelot 路由 请求聚合 服务发现 认证 鉴权 限流熔断 内置负载均衡器 Consul 自动服务发现 健康检查 通过Ocelot搭建API网关 服务注册 负载均衡 1. ...
- eee
package demo; public class Phone { String phonexinghao; String phonepinpai; public void shouji (){ S ...
- Kafka+OpenCV 实现实时流视频处理
1. 启动Kafka Server bin/kafka-server-start.sh config/server.properties & 2. 创建一个新topic bin/kafka- ...
- SQL 基础学习(1):下载DB Browser for SQLite. 下载graphviz(为了使用Rails ERD的前提)出现❌,已debug.
SQL is a standard language for storing, manipulating and retrieving data in databases. 关系型数据库:RDBMS( ...
- 运维案例 | Exchange2010数据库损坏的紧急修复思路
关注嘉为科技,获取运维新知 Exchange后端数据库故障,一般都会是比较严重的紧急故障,因为这会直接影响到大面积用户的正常使用,而且涉及到用户数据.一旦遇到这种级别的故障,管理员往往都是在非常紧 ...
- hdoj3138
题意:略 各点向原信念连INF+1的边,不同信念连INF的边,这样割原信念花费大一点.然后好友连1的边.最小割的结果-n*INF就是答案,因为割到哪边最少都要INF. #include <ios ...
- 思科模拟器PacketTracer7--利用一台交换机将两台pc划分到不同vlan下
实验2—3 实验内容:将同一交换机下的两台pc划分到不同vlan中 实验工具:思科模拟器PacketTracer7 使用设备:一台交换机,两台PC 实验步骤: 一.配置网络拓扑图 注:1.连线可选择闪 ...