Java:对象的强、软、弱、虚引用
转自:
http://zhangjunhd.blog.51cto.com/113473/53092

ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);

MyObject aRef = new MyObject();
SoftReference aSoftRef=new SoftReference(aRef);
此时,对于这个MyObject对象,有两个引用路径,一个是来自SoftReference对象的软引用,一个来自变量aReference的强引用,所以这个MyObject对象是强可及对象。
aRef = null;
MyObject anotherRef=(MyObject)aSoftRef.get();
重新获得对该实例的强引用。而回收之后,调用get()方法就只能得到null了。
ReferenceQueue queue = new ReferenceQueue();
SoftReference ref=new SoftReference(aMyObject, queue);
那么当这个SoftReference所软引用的aMyOhject被垃圾收集器回收的同时,ref所强引用的SoftReference对象被列入ReferenceQueue。也就是说,ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。另外从ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。
SoftReference ref = null;
while ((ref = (EmployeeRef) q.poll()) != null) {
// 清除ref
}
public class Employee {
private String id;// 雇员的标识号码
private String name;// 雇员姓名
private String department;// 该雇员所在部门
private String Phone;// 该雇员联系电话
private int salary;// 该雇员薪资
private String origin;// 该雇员信息的来源
// 构造方法
public Employee(String id) {
this.id = id;
getDataFromlnfoCenter();
}
// 到数据库中取得雇员信息
private void getDataFromlnfoCenter() {
// 和数据库建立连接井查询该雇员的信息,将查询结果赋值
// 给name,department,plone,salary等变量
// 同时将origin赋值为"From DataBase"
}
//setter/getter
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getPhone() {
return Phone;
}
public void setPhone(String phone) {
Phone = phone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
}
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Hashtable; public class EmployeeCache {
static private EmployeeCache cache;// 一个Cache实例
private Hashtable<String,EmployeeRef> employeeRefs;// 用于Chche内容的存储
private ReferenceQueue<Employee> q;// 垃圾Reference的队列 // 继承SoftReference,使得每一个实例都具有可识别的标识, 并且该标识与其在HashMap内的key相同。
private class EmployeeRef extends SoftReference<Employee> {
private String _key = ""; public EmployeeRef(Employee em, ReferenceQueue<Employee> q) {
super(em, q);
_key = em.getId();
}
} // 构建一个缓存器实例
private EmployeeCache() {
employeeRefs = new Hashtable<String,EmployeeRef>();
q = new ReferenceQueue<Employee>();
} // 取得缓存器实例
public static EmployeeCache getInstance() {
if (cache == null) {
cache = new EmployeeCache();
}
return cache;
} // 以软引用的方式对一个Employee对象的实例进行引用并保存该引用
private void cacheEmployee(Employee em) {
cleanCache();// 清除垃圾引用
EmployeeRef ref = new EmployeeRef(em, q);
employeeRefs.put(em.getId(), ref);
} // 依据所指定的ID号,重新获取相应Employee对象的实例
public Employee getEmployee(String ID) {
Employee em = null;
// 缓存中是否有该Employee实例的软引用,如果有,从软引用中取得。
if (employeeRefs.containsKey(ID)) {
EmployeeRef ref = (EmployeeRef) employeeRefs.get(ID);
em = (Employee) ref.get();
}
// 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,并保存对这个新建实例的软引用
if (em == null) {
em = new Employee(ID);
System.out.println("Retrieve From EmployeeInfoCenter. ID=" + ID);
this.cacheEmployee(em);
}
return em;
} // 清除那些所软引用的Employee对象已经被回收的EmployeeRef对象
private void cleanCache() {
EmployeeRef ref = null;
while ((ref = (EmployeeRef) q.poll()) != null) {
employeeRefs.remove(ref._key);
}
} // 清除Cache内的全部内容
public void clearCache() {
cleanCache();
employeeRefs.clear();
System.gc();
System.runFinalization();
} }
无意识对象保留最常见的原因是使用Map将元数据与临时对象(transient object)相关联。假定一个对象具有中等生命周期,比分配它的那个方法调用的生命周期长,但是比应用程序的生命周期短,如客户机的套接字连接。需要将一些元数据与这个套接字关联,如生成连接的用户的标识。在创建Socket时是不知道这些信息的,并且不能将数据添加到Socket对象上,因为不能控制 Socket 类或者它的子类。这时,典型的方法就是在一个全局 Map 中存储这些信息,如下面的 SocketManager 类所示:使用一个全局 Map 将元数据关联到一个对象。
public class SocketManager {
private Map<Socket, User> m = new HashMap<Socket, User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
public void removeUser(Socket s) {
m.remove(s);
}
}
import java.util.WeakHashMap;
class Element {
private String ident;
public Element(String id) {
ident = id;
}
public String toString() {
return ident;
}
public int hashCode() {
return ident.hashCode();
}
public boolean equals(Object obj) {
return obj instanceof Element && ident.equals(((Element) obj).ident);
}
protected void finalize(){
System.out.println("Finalizing "+getClass().getSimpleName()+" "+ident);
}
}
class Key extends Element{
public Key(String id){
super(id);
}
}
class Value extends Element{
public Value (String id){
super(id);
}
}
public class CanonicalMapping {
public static void main(String[] args){
int size = 1000;
Key[] keys = new Key[size];
WeakHashMap<Key,Value> map = new WeakHashMap<Key,Value>();
for(int i=0; i<size; i++){
Key k = new Key(Integer.toString(i));
Value v = new Value(Integer.toString(i));
if(i%3 == 0)
keys[i]=k;
map.put(k, v);
}
System.gc();
}
}
public class SocketManager {
private Map<Socket,User> m = new WeakHashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
}
4.4配合使用引用队列

Java:对象的强、软、弱、虚引用的更多相关文章
- java中的强,软,弱,虚引用
引用的应用场景 我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型.这正是Java中弱引用和软引用的主要区别. 如果一个对象只有弱引用指向 ...
- java中强,软,弱,虚引用 以及WeakHahMap
java中强,软,弱,虚引用 以及WeakHahMap 一:强软引用: 参考:http://zhangjunhd.blog.51cto.com/113473/53092/进行分析 packa ...
- Java:对象的强、软、弱和虚引用
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
- Java对象的强、软、弱和虚引用详解
1.对象的强.软.弱和虚引用 转自:http://zhangjunhd.blog.51cto.com/113473/53092/ 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器
//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...
- Java:对象的强、软、弱和虚引用[转]
原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- Java对象的强、软、弱和虚引用+ReferenceQueue
Java对象的强.软.弱和虚引用+ReferenceQueue 一.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足 ...
- Java对象的强、软、弱和虚引用
本文介绍Java对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象 ...
- Java:对象的强、软、弱和虚引用的区别
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
随机推荐
- bootscript/javascript组件
javascript组件 (1)每一个插件(带有js功能的组件),想使用bootstrap插件,一个是要去写他的html,第二个是使用CSS去修饰它,再引入相应的js文件. bootstrap框架 ...
- C++ 的二进制语法与语义
/* 转载请注明出处:http://www.cnblogs.com/Martinium/p/binary_literal.html */ 二进制的语法 C/C++ 默认数字使用十进制,八进制使用前缀 ...
- Android之EACCES (Permission denied)与Permission denied异常探密
话说,Accipiter君,最近又开始怒学Android了,记得刚开始还是09年学的,现在的手机还是华为出的最早的一款Android手机C8500,那时候就想好好学习Android,赚点小钱,可是~~ ...
- 【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】
一.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: package day16.utils; import java.io.IOException; import java.lang.ref ...
- Android中的ANR
有过Android开发经历的人都不会对ANR陌生,它和崩溃一样是程序设计的问题.本文将以较为深入的视角来介绍什么是ANR,出现场景,如何避免以及如何定位分析ANR,希望可以帮助大家在编写程序时有所帮助 ...
- PHP 检查并创建多级目录
<?php //检查并创建多级目录 function checkDir($path){ $pathArray = explode('/',$path); $no ...
- React的双向绑定
以前对于双向绑定概念来自于Angular.js,现在我用我感兴趣的react.js来实现这样的方式.有2种方式分析,1:不用插件,2:用插件 (引入react.js操作省略...) 不用插件: 先创建 ...
- SOAPUI使用教程-MockOperations和响应
如前所述,一个MockService有多个MockOperations其中每个可以包含任意数量的MockResponse消息; 也就是说,一个MockService响应实际上包括若干预设响应之间发生变 ...
- [转] 传统 Ajax 已死,Fetch 永生
原谅我做一次标题党,Ajax 不会死,传统 Ajax 指的是 XMLHttpRequest(XHR),未来现在已被 Fetch 替代. 最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的 ...
- Linux CentOS6.5下安装Oracle ASM
Oracle版本:Oracle 11g 1.确定自己的Linux版本: [root@localhost ~]#uname -r 2.6.32-431.el6.x86_64 2.6.32-431.el6 ...