好比,咱们假设图2中引用①和③为强引用,⑤为软引用,⑦为弱引用,对于对象5按照这两个判断原则,路径①-⑤取最弱的引用⑤,所以该路径对对象5的引用为软引用。一样,③-⑦为弱引用。在这两条路径之间取最强的引用,因而对象5是一个软可达对象。 java
首先,咱们看一个雇员信息查询系统的实例。咱们将使用一个Java语言实现的雇员信息查询系统查询存储在磁盘文件或者数据库中的雇员人事档案信息。做为一个用户,咱们彻底有可能须要回头去查看几分钟甚至几秒钟前查看过的雇员档案信息(一样,咱们在浏览WEB页面的时候也常常会使用“后退”按钮)。这时咱们一般会有两种程序实现方式:一种是把过去查看过的雇员信息保存在内存中,每个存储了雇员档案信息的Java对象的生命周期贯穿整个应用程序始终;另外一种是当用户开始查看其余雇员的档案信息的时候,把存储了当前所查看的雇员档案信息的Java对象结束引用,使得垃圾收集线程能够回收其所占用的内存空间,当用户再次须要浏览该雇员的档案信息的时候,从新构建该雇员的信息。很显然,第一种实现方法将形成大量的内存浪费,而第二种实现的缺陷在于即便垃圾收集线程尚未进行垃圾收集,包含雇员档案信息的对象仍然无缺地保存在内存中,应用程序也要从新构建一个对象。咱们知道,访问磁盘文件、访问网络资源、查询数据库等操做都是影响应用程序执行性能的重要因素,若是能从新获取那些还没有被回收的Java对象的引用,必将减小没必要要的访问,大大提升程序的运行速度。 算法
MyObject aRef = new MyObject(); SoftReference aSoftRef = new SoftReference( aRef );
aRef = null ;
MyObject anotherRef =(MyObject) aSoftRef .get()
ReferenceQueue queue = new ReferenceQueue(); SoftReference ref = new SoftReference( aMyObject , queue );
SoftReference ref = null ; while ((ref = (SoftReference)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" } …… }
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 synchronized 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 ); } } }