下图为对象层次的引用
6、相关应用
在java.lang.ref包中提供了三个类:SoftReference类、WeakReference类和PhantomReference类,它 们分别代表软引用、弱引用和虚引用。ReferenceQueue类表示引用队列,它可以和这三种引用类联合使用,以便跟踪Java虚拟机回收所引用的对 象的活动。以下程序创建了一个String对象、ReferenceQueue对象和WeakReference对象:
以上程序代码执行完毕,内存中引用与对象的关系如图2所示
- String
str = new String("hello"); //① - ReferenceQueue
rq = new ReferenceQueue(); //② - WeakReference
wf = new WeakReference(str, rq); //③ - str=null;
//④ - //两次催促垃圾回收器工作,提高"hello"对象被回收的可能性
- System.gc();
//⑤ - System.gc();
//⑥ - String
str1=wf.get(); //⑦ 假如"hello"对象被回收,str1为null - Reference
ref=rq.poll(); //⑧
- package
test; -
- import
java.lang.ref.*; - import
java.util.*; -
- class
Grocery { -
private static final int SIZE = 10000; -
// 属性d使得每个Grocery对象占用较多内存,有80K左右 -
private double[] d = new double[SIZE]; -
private String id; -
-
public Grocery(String id) { -
this.id = id; -
} -
-
public String toString() { -
return id; -
} -
-
public void finalize() { -
System.out.println("Finalizing " + id); -
} - }
-
- public
class References { -
private static ReferenceQueue rq = new ReferenceQueue(); -
-
public static void checkQueue() { -
Reference inq = rq.poll(); -
// 从队列中取出一个引用 -
if (inq != null) -
System.out.println("In queue: " + inq + " : " + inq.get()); -
} -
-
public static void main(String[] args) { -
final int size = 10; -
// 创建10个Grocery对象以及10个软引用 -
Set sa = new HashSet(); -
for (int i = 0; i < size; i++) { -
SoftReference ref = new SoftReference(new Grocery("soft" + i), rq); -
System.out.println("Just created soft: " + ref.get()); -
sa.add(ref); -
} -
System.gc(); -
checkQueue(); -
System.out.println("---------------------------------------------------"); -
// 创建10个Grocery对象以及10个弱引用 -
Set wa = new HashSet(); -
for (int i = 0; i < size; i++) { -
WeakReference ref = new WeakReference(new Grocery ("weak " + i), rq); -
System.out.println("Just created weak: " + ref.get()); -
wa.add(ref); -
} -
System.gc(); -
checkQueue(); -
System.out.println("---------------------------------------------------"); -
// 创建10个Grocery对象以及10个虚引用 -
Set pa = new HashSet(); -
for (int i = 0; i < size; i++) { -
PhantomReference ref =new PhantomReference(new Grocery("Phantom " + i), rq); -
System.out.println("Just created Phantom: " + ref.get()); -
pa.add(ref); -
} -
System.gc(); -
checkQueue(); -
} - }
- package
test; -
- import
java.lang.ref.*; - import
java.util.*; -
- class
Grocery { -
private static final int SIZE = 10000; -
// 属性d使得每个Grocery对象占用较多内存,有80K左右 -
private double[] d = new double[SIZE]; -
private String id; -
-
public Grocery(String id) { -
this.id = id; -
} -
-
public String toString() { -
return id; -
} -
-
public void finalize() { -
System.out.println("Finalizing " + id); -
} - }
-
- public
class References { -
private static ReferenceQueue rq = new ReferenceQueue(); -
-
public static void checkQueue() { -
Reference inq = rq.poll(); -
// 从队列中取出一个引用 -
if (inq != null) -
System.out.println("In queue: " + inq + " : " + inq.get()); -
} -
-
public static void main(String[] args) { -
final int size = 10; -
// 创建10个Grocery对象以及10个软引用 -
Set sa = new HashSet(); -
for (int i = 0; i < size; i++) { -
SoftReference ref = new SoftReference(new Grocery("soft" + i), rq); -
System.out.println("Just created soft: " + ref.get()); -
sa.add(ref); -
} -
System.gc(); -
checkQueue(); -
System.out.println("---------------------------------------------------"); -
// 创建10个Grocery对象以及10个弱引用 -
Set wa = new HashSet(); -
for (int i = 0; i < size; i++) { -
WeakReference ref = new WeakReference(new Grocery ("weak " + i), rq); -
System.out.println("Just created weak: " + ref.get()); -
wa.add(ref); -
} -
System.gc(); -
checkQueue(); -
System.out.println("---------------------------------------------------"); -
// 创建10个Grocery对象以及10个虚引用 -
Set pa = new HashSet(); -
for (int i = 0; i < size; i++) { -
PhantomReference ref =new PhantomReference(new Grocery("Phantom " + i), rq); -
System.out.println("Just created Phantom: " + ref.get()); -
pa.add(ref); -
} -
System.gc(); -
checkQueue(); -
} - }
- package
test; -
- import
java.util.*; - import
java.lang.ref.*; -
- class
Key { -
String id; -
-
public Key(String id) { -
this.id = id; -
} -
public String toString() { -
return id; -
} -
public int hashCode() { -
return id.hashCode(); -
} -
public boolean equals(Object r) { -
return (r instanceof Key) && id.equals(((Key) r).id); -
} -
public void finalize() { -
System.out.println("Finalizing Key " + id); -
} - }
- class
Value { -
String id; -
public Value(String id) { -
this.id = id; -
} -
public String toString() { -
return id; -
} -
public void finalize() { -
System.out.println("Finalizing Value " + id); -
} - }
-
- public
class MapCache { -
public static void main(String[] args) throws Exception { -
int size = 1000;// 或者从命令行获得size的大小 -
if (args.length > 0) -
size = Integer.parseInt(args[0]); -
Key[] keys = new Key[size]; // 存放键对象的强引用 -
WeakHashMap whm = new WeakHashMap(); -
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; // 使Key对象持有强引用 -
whm.put(k, v); // 使Key对象持有弱引用 -
} -
// 催促垃圾回收器工作 -
System.gc();// 把CPU让给垃圾回收器线程 -
Thread.sleep(8000); -
} - }
程序输出结果:
- Finalizing
Key 137 - Finalizing
Key 368 - Finalizing
Key 415 - Finalizing
Key 470 - Finalizing
Key 514 - Finalizing
Key 557 - Finalizing
Key 601 - Finalizing
Key 643 - Finalizing
Key 686 - Finalizing
Key 730 - Finalizing
Key 775 - Finalizing
Key 817 - Finalizing
Key 862 - Finalizing
Key 907 - Finalizing
Key 952 - Finalizing
Key 995 - Finalizing
Key 998 - Finalizing
Key 997
7、使用软引用构建敏感数据的缓存
- 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" -
} - ……
- import
java.lang.ref.ReferenceQueue; - import
java.lang.ref.SoftReference; - import
java.util.Hashtable; - public
class EmployeeCache { -
static private EmployeeCache cache;// 一个Cache实例 -
private Hashtable employeeRefs;// 用于Cache内容的存储 -
private ReferenceQueue q;// 垃圾Reference的队列 -
-
// 继承SoftReference,使得每一个实例都具有可识别的标识。 -
// 并且该标识与其在HashMap内的key相同。 -
private class EmployeeRef extends SoftReference { -
private String _key = ""; -
-
public EmployeeRef(Employee em, ReferenceQueue q) { -
super(em, q); -
_key = em.getID(); -
} -
} -
-
// 构建一个缓存器实例 -
private EmployeeCache() { -
employeeRefs = new Hashtable(); -
q = new ReferenceQueue(); -
} -
-
// 取得缓存器实例 -
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(); -
} - }
- 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 map=new WeakHashMap(); -
for(int i=0;i< SPAN> -
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 m = new WeakHashMap(); -
-
public void setUser(Socket s, User u) { -
m.put(s, u); -
} -
public User getUser(Socket s) { -
return m.get(s); -
} - }