//看之前先要知道java里面的四种引用。
package com.zby.ref; import sun.misc.Cleaner; /**
* 引用对象的抽象基础类。这个类定义了所有引用对象的公共操作。因为引用对象在跟垃圾收集器紧密合作中被实现,所以这个类不能被引用对象直接继承。
*
* @author zhoubaiyun
*
* @param <T>
*/
public abstract class Reference<T> {
/*
* 一个引用实例是在这四个可能的内部状态之一。
*
* 活跃状态:服从于垃圾处理器的特别处理。有时在收集器检测到可达到的引用对象已经改变成为适当的状态,收集器改变实例的状态为挂起或者不活跃,
* 依赖于是否这个实例在它创建时是否注册。在之前的情况收集器还会添加实例到挂起引用列表。 最新创建的实例使活跃状态。
*
* 挂起状态: 一个挂起引用列表中等待被引用处理线程排队的元素。没有注册的实例不可能有这个状态。
*
* 排队状态:一个队列里面的在创建时就被注册的实例元素。当一个实例被从他自己的引用队列移除,他就变成不活跃状态了。没有注册的实例不可能有这个状态。
*
* 不活跃状态:无所事事。一个实例变成不活跃状态就不可能再改变状态了。
*
* 状态像下面这样被编码到queue和next字段:
*
* 活跃:实例注册时queue = ReferenceQueue或者如果实例没有被注册queue=ReferenceQueue.NULL;next=null.
*
* 挂起:实例注册时queue = ReferenceQueue;next=queue里面的下一个实例,如果实例是队列最后一个元素,next=this
*
* 排队:queue = ReferenceQueue.ENQUEUED;next=queue里面的下一个实例,如果实例是队列最后一个元素,next=this
*
* 不活跃:queue = ReferenceQueue.NULL; next = this.
*
* 有了这些约束,收集器为了确定一个引用对象是否需要特别对待只需要检查next字段:如果next字段是null这个实例就是活跃的;如果
* 不为null,这收集器就应该正常对待这个实例了。
*
* 为了保证并发收集器能发现活跃引用对象而不干涉可能在这些对象上调用queue()方法的应用线程,收集器应该通过已发现的字段链接已发现的对象。
*/
private T referent; //GC要特殊对待的对象
ReferenceQueue<? super T> queue; Reference next; private transient Reference<T> discovered; //VM使用 //对象过去常常是跟垃圾收集器同步的。收集器在每一个收集周期开始时必须获取这个锁。
//因此至关重要的是任何持有这个锁的代码必须尽快完成,不分配新对象,避免调用用户代码。
private static class Lock { }; private static Lock lock = new Lock(); //等待排队的引用列表。当引用处理器线程移除引用,收集器就他们加到这个列表。这个列表被上面的锁对象保护。
private static Reference pending = null; //排队挂起引用的高优先级线程
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);
}
}
} static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
//这个就是取最上层的线程组,看起来写的很溜
//主线程有一个main线程组[Thread[main,5,main], null, null, null]
//上面还有一个system线程组[Thread[Reference Handler,10,system], Thread[Finalizer,8,system], Thread[Signal Dispatcher,9,system], Thread[Attach Listener,5,system]]。
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent()); //启动一个引用处理线程
Thread handler = new ReferenceHandler(tg, "Reference Handler");
//如果还有系统独有的优先级比MAX_PRIORITY这个高,那么就高的
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
} /*GC要特殊对待的对象的访问器和设置器*/
/**
* 返回当前引用对象的GC要特殊对待的对象,不管这个对象已经被程序还是垃圾收集器清理了都返回null
* @return
*/
public T get() {
return this.referent;
} /**
* 清理这个引用对象,执行这个方法不会引起对象进入排队队列。
*
* 这个方法只会被java代码执行;当垃圾收集器执行清理会很直接,不会执行这个方法。
*/
public void clear() {
this.referent = null;
} /*查询操作*/
/**
* 告诉你这个引用对象是否一家被加入排队队列,不管是程序或者垃圾收集器干的。如果这个引用对象在创建时没有被注册到队列,这个方法会返回false。
* @return
*/
public boolean isEnqueued() {
//在内部状态中可以看出来,这个方法实际上不管实例是挂起还是排队都会检查到
synchronized (this) {
return (this.queue != ReferenceQueue.NULL) && (this.next != null);
}
}
/**
* 添加这个引用对象到它注册到的任何队列里面。
* 这个方法只会被java代码执行;当垃圾收集器执行清理会很直接,不会执行这个方法。
* @return 如果这个引用对象被成功加入排队队列返回true,如果它已经被加入了排队队列或者在创建时没有注册到一个队列返回false。
*/
public boolean enqueue() {
return this.queue.enqueue(this);
} /*构造方法*/
Reference(T referent) {
this(referent, null);
} Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
}

看完后就明白了一个问题,JVM运行的时候至少开启几个线程?(答案是五个!)

java.lang.ref.Reference<T>的更多相关文章

  1. 深入探讨 java.lang.ref 包--转

    概述 Java.lang.ref 是 Java 类库中比较特殊的一个包,它提供了与 Java 垃圾回收器密切相关的引用类.这些引用类对象可以指向其它对象,但它们不同于一般的引用,因为它们的存在并不防碍 ...

  2. 深入探讨 java.lang.ref 包

    深入探讨 java.lang.ref 包 本文主要探讨了 java.lang.ref 包的使用方法,以及源码解读.并就该包在不同 JVM 上的表现进行了比较与分析.通过阅读本文,读者可以加深对 jav ...

  3. ANDROID_MARS学习笔记_S04_009_用java.lang.ref.SoftReference作缓存,android.os.Handler和new Thread异步加载略图片

    一.简介 二.代码流程 1.private Map<String, SoftReference<Drawable>> imageCache = new HashMap<S ...

  4. java.lang.Thread

    package java.lang; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java. ...

  5. [java] [error] java.lang.OutOfMemoryError: unable to create new native thread

    前言 最近公司的服务器出现了oom的报错,经过一番排查,终于找到了原因.写下这篇博客是为了记录下查找的过程,也是为了帮助那些跟我门遇到的情况相同的人可以更快的寻找到答案. 环境 系统:linux(ce ...

  6. java.lang包

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.特性——不用import 2.String String x = "abc"; < ...

  7. java中的Reference

    这两天又重新学习了一下Reference,根据网上的资源做了汇总. Java中的引用主要有4种: 强引用 StrongReference: Object obj = new Object(); obj ...

  8. Java中的Reference类使用

    Java 2 平台引入了 java.lang.ref 包,这个包下面包含了几个Reference相关的类,Reference相关类将Java中的引用也映射成一个对象,这些类还提供了与垃圾收集器(gar ...

  9. 应用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap space)

    http://www.educity.cn/wenda/351088.html 使用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap s ...

随机推荐

  1. zigbee之MAC地址发送

    TI cc2530在出厂时候每一个芯片都固化了一个唯一的8个字节的地址,MAC或者IEEE地址. 协调器模块的MAC地址为:0x00124B000716550F(注意自己的是多少!!) 终端的MAC地 ...

  2. <abbr> 元素的样式为显示在文本底部的一条虚线边框,当鼠标悬停在上面时会显示完整的文本(只要您为 <abbr> title 属性添加了文本)

    <abbr title="World Wide Web">WWW</abbr><br><abbr title="Real Sim ...

  3. Python基础入门-while循环示例

    闲来无事! 想写一些基础的东西! 比如今天的while循环,,,,,, 很多python初学者,最开始学习python的时候,会被while循环给干蒙蔽! 那么今天,小编为大家讲解一些基础的实例,来帮 ...

  4. NSString 对象保存在哪? @“xxx”和 stringWithFormat:@"xxx" 区别?

    NSString *str1=@"string";//这种是保存在常量池 NSString *str2=@"string"; NSLog(@"str1 ...

  5. 【Java学习01】:win7环境安装JDK

    最近开始学习java,从第一步做起吧.win7中安装jdk非常简单,大牛勿喷. 1.下载JDK并执行安装. 访问网站www.java.com,选择win7版本的JDK下载.下载后双击安装(比较慢,耐心 ...

  6. XE中rectangle实现渐变

    Fill -> Kind -> Gradient(选项) -> Gradient(Edit) 添加颜色即可

  7. 将以太坊封装为 ERC20

    将以太坊封装为 ERC20 TOKEN 很多 DAPP 都是在处理 ERC20接口的 token, 其实很容易将以太坊封装为 ERC20,这样就可以统一处理, 至少我目前在做的雷电网络就是这么处理的. ...

  8. 201621123012 《Java程序设计》第1周学习总结

    1. 本章学习总结 学习了java的理论知识和它与C语言的差别,什么是JVM,区分JRE与JDK并学习JAVA环境的安装.熟悉控制台下的常用命令,java函数的编写.熟练使用编写JAVA所需要的工具( ...

  9. PHP7 - MongoDB Driver 使用心得

    php7 只能使用Mongodb driver来驱动mongodb. 使用Mongodb Driver连接数据库 刚开始使用Mongodb Driver的时候我是拒绝的.查看官方文档只看到一排的类和不 ...

  10. react.js学习之路一

    今天新老大来了,我们要学习他使用的框架react.js,现在是两眼一抹黑,对于我这个前端菜鸟来说,是真正的重新开始,好了,不说那么多了,开始随便记录我的学习,之后再整理内容. (1)对于react来说 ...