好比,咱們假設圖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 ); } } }