Java對象的強、軟、弱和虛引用 之間的區別

 

Java對象的強、軟、弱和虛引用 之間的區別
2008-07-18 13:33
在JDK1.2以前的版本中,當一個對象不被任何變量引用,那麼程序就無法再使用這個對象。也就是說,只有對象處於可觸及狀態,程序才能使用它。這 就像在日常生活中,從商店購買了某樣物品後,如果有用,就一直保留它,否則就把它扔到垃圾箱,由清潔工人收走。一般說來,如果物品已經被扔到垃圾箱,想再 把它撿回來使用就不可能了。

    但有時候情況並不這麼簡單,你可能會遇到類似雞肋一樣的物品,食之無味,棄之可惜。這種物品現在已經無用了,保留它會佔空間,但是立刻扔掉它也不划算,因 爲也許將來還會派用場。對於這樣的可有可無的物品,一種折衷的處理辦法是:如果家裏空間足夠,就先把它保留在家裏,如果家裏空間不夠,即使把家裏所有的垃 圾清除,還是無法容納那些必不可少的生活用品,那麼再扔掉這些可有可無的物品。

    從JDK1.2版本開始,把對象的引用分爲四種級別,從而使程序能更加靈活的控制對象的生命週期。這四種級別由高到低依次爲:強引用、軟引用、弱引用和虛引用。


1.強引用
    本章前文介紹的引用實際上都是強引用,這是使用最普遍的引用。如果一個對象具有強引用,那就類似於必不可少的生活用品,垃圾回收器絕不會回收它。當內存空 間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足問題。


2.軟引用(SoftReference)

    如果一個對象只具有軟引用,那就類似於可有可物的生活用品。如果內存空間足夠,垃圾回收器就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。
軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

3.弱引用(WeakReference)
    如果一個對象只具有弱引用,那就類似於可有可物的生活用品。弱引用與軟引用的區別在於:只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它 所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程, 因此不一定會很快發現那些只具有弱引用的對象。 
弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。


4.虛引用(PhantomReference)
    "虛引用"顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命週期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收。
虛引用主要用來跟蹤對象被垃圾回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃 圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中。程序可以通過判斷引用隊列中是 否已經加入了虛引用,來了解

    被引用的對象是否將要被垃圾回收。程序如果發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的內存被回收之前採取必要的行動。

    在本書中,"引用"既可以作爲動詞,也可以作爲名詞,讀者應該根據上下文來區分"引用"的含義。
在java.lang.ref包中提供了三個類:SoftReference類、WeakReference類和PhantomReference類,它 們分別代表軟引用、弱引用和虛引用。ReferenceQueue類表示引用隊列,它可以和這三種引用類聯合使用,以便跟蹤Java虛擬機回收所引用的對 象的活動。以下程序創建了一個String對象、ReferenceQueue對象和WeakReference對象:

//創建一個強引用
String str = new String("hello");

//創建引用隊列, <String>爲範型標記,表明隊列中存放String對象的引用
ReferenceQueue<String> rq = new ReferenceQueue<String>();

//創建一個弱引用,它引用"hello"對象,並且與rq引用隊列關聯
//<String>爲範型標記,表明WeakReference會弱引用String對象
WeakReference<String> wf = new WeakReference<String>(str, rq);

以上程序代碼執行完畢,內存中引用與對象的關係如圖11-10所示。

圖11-10 "hello"對象同時具有強引用和弱引用
在圖11-10中,帶實線的箭頭表示強引用,帶虛線的箭頭表示弱引用。從圖中可以看出,此時"hello"對象被str強引用,並且被一個WeakReference對象弱引用,因此"hello"對象不會被垃圾回收。
在以下程序代碼中,把引用"hello"對象的str變量置爲null,然後再通過WeakReference弱引用的get()方法獲得"hello"對象的引用:

String str = new String("hello"); //① 
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //② 
WeakReference<String> wf = new WeakReference<String>(str, rq); //③

str=null; //④取消"hello"對象的強引用
String str1=wf.get(); //⑤假如"hello"對象沒有被回收,str1引用"hello"對象

//假如"hello"對象沒有被回收,rq.poll()返回null
Reference<? extends String> ref=rq.poll(); //⑥


    執行完以上第④行後,內存中引用與對象的關係如圖11-11所示,此 時"hello"對象僅僅具有弱引用,因此它有可能被垃圾回收。假如它還沒有被垃圾回收,那麼接下來在第⑤行執行wf.get()方法會返回 "hello"對象的引用,並且使得這個對象被str1強引用。再接下來在第⑥行執行rq.poll()方法會返回null,因爲此時引用隊列中沒有任何 引用。ReferenceQueue的poll()方法用於返回隊列中的引用,如果沒有則返回null。


圖11-11 "hello"對象只具有弱引用

    在以下程序代碼中,執行完第④行後,"hello"對象僅僅具有弱引用。接下來兩次調用System.gc()方法,催促垃圾回收器工作,從而提高 "hello"對象被回收的可能性。假如"hello"對象被回收,那麼WeakReference對象的引用被加入到ReferenceQueue中, 接下來wf.get()方法返回null,並且rq.poll()方法返回WeakReference對象的引用。圖11-12顯示了執行完第⑧行後內存 中引用與對象的關係。

String str = new String("hello"); //①
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //② 
WeakReference<String> wf = new WeakReference<String>(str, rq); //③
str=null; //④

//兩次催促垃圾回收器工作,提高"hello"對象被回收的可能性
System.gc(); //⑤
System.gc(); //⑥
String str1=wf.get(); //⑦ 假如"hello"對象被回收,str1爲null
Reference<? extends String> ref=rq.poll(); //⑧


圖11-12 "hello"對象被垃圾回收,弱引用被加入到引用隊列


    在以下例程11-15的References類中,依次創建了10個軟引用、10個弱引用和10個虛引用,它們各自引用一個Grocery對象。從程序運 行時的打印結果可以看出,虛引用形同虛設,它所引用的對象隨時可能被垃圾回收,具有弱引用的對象擁有稍微長的生命週期,當垃圾回收器執行回收操作時,有可 能被垃圾回收,具有軟引用的對象擁有較長的生命週期,但在Java虛擬機認爲內存不足的情況下,也會被垃圾回收。

例程11-15 References.java
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<Grocery> rq = new ReferenceQueue<Grocery>();
public static void checkQueue() {
Reference<? extends Grocery> 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<SoftReference<Grocery>> sa = new HashSet<SoftReference<Grocery>>();
for(int i = 0; i < size; i++) {
SoftReference<Grocery> ref=
new SoftReference<Grocery>(new Grocery("Soft " + i), rq);
System.out.println("Just created: " +ref.get());
sa.add(ref);
}
System.gc();
checkQueue();

//創建10個Grocery對象以及10個弱引用
Set<WeakReference<Grocery>> wa = new HashSet<WeakReference<Grocery>>();
for(int i = 0; i < size; i++) {
WeakReference<Grocery> ref=
new WeakReference<Grocery>(new Grocery("Weak " + i), rq);
System.out.println("Just created: " +ref.get());
wa.add(ref); 
}
System.gc();
checkQueue();

//創建10個Grocery對象以及10個虛引用
Set<PhantomReference<Grocery>> pa = new HashSet<PhantomReference<Grocery>>();
for(int i = 0; i < size; i++) {
PhantomReference<Grocery>ref = 
new PhantomReference<Grocery>(new Grocery("Phantom " + i), rq);
System.out.println("Just created: " +ref.get());
pa.add(ref);
}
System.gc();
checkQueue();
}
}


在Java集合中有一種特殊的Map類型:WeakHashMap, 在這種Map中存放了鍵對象的弱引用,當一個鍵對象被垃圾回收,那麼相應的值對象的引用會從Map中刪除。WeakHashMap能夠節約存儲空間,可用 來緩存那些非必須存在的數據。關於Map接口的一般用法,可參見本書第15章的15.4節(Map)。

    以下例程11-16的MapCache類的main()方法創建了一個WeakHashMap對象,它存放了一組Key對象的弱引用,此外main()方法還創建了一個數組對象,它存放了部分Key對象的強引用。

例程11-16 MapCache.java
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<Key,Value> whm = 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; //使Key對象持有強引用 
whm.put(k, v); //使Key對象持有弱引用
}
//催促垃圾回收器工作
System.gc();

//把CPU讓給垃圾回收器線程
Thread.sleep(8000);
}
}

以上程序的部分打印結果如下:

Finalizing Key 998
Finalizing Key 997
Finalizing Key 995
Finalizing Key 994
Finalizing Key 992
Finalizing Key 991
Finalizing Key 989
Finalizing Key 988
Finalizing Key 986
Finalizing Key 985
Finalizing Key 983

    從打印結果可以看出,當執行System.gc()方法後,垃圾回收器只會回收那些僅僅持有弱引用的Key對象。id可以被3整數的Key對象持有強引用,因此不會被回收。



url2:http://icanfly.iteye.com/blog/1209389

1.對象的強、軟、弱和虛引用 
在JDK 1.2以前的版本中,若一個對象不被任何變量引用,那麼程序就無法再使用這個對象。也就是說,只有對象處於可觸及(reachable)狀態,程序才能使用它。從JDK 1.2版本開始,把對象的引用分爲4種級別,從而使程序能更加靈活地控制對象的生命週期。這4種級別由高到低依次爲:強引用、軟引用、弱引用和虛引用。圖1爲對象應用類層次。 
 
圖1 
⑴強引用(StrongReference) 
強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足的問題。 

⑵軟引用(SoftReference) 
如果一個對象只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存(下文給出示例)。 
軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。 

⑶弱引用(WeakReference) 
弱引用與軟引用的區別在於:只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程,因此不一定會很快發現那些只具有弱引用的對象。 
弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。 

⑷虛引用(PhantomReference) 
“虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命週期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。 
虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之 關聯的引用隊列中。 
ReferenceQueue queue = new ReferenceQueue (); 
PhantomReference pr = new PhantomReference (object, queue); 
程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。如果程序發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的內存被回收之前採取必要的行動。 
2.對象可及性的判斷 
    在很多時候,一個對象並不是從根集直接引用的,而是一個對象被其他對象引用,甚至同時被幾個對象所引用,從而構成一個以根集爲頂的樹形結構。如圖2所示 
 
圖2 
    在這個樹形的引用鏈中,箭頭的方向代表了引用的方向,所指向的對象是被引用對象。由圖可以看出,從根集到一個對象可以由很多條路徑。比如到達對象5的路徑就有①-⑤,③-⑦兩條路徑。由此帶來了一個問題,那就是某個對象的可及性如何判斷: 
◆單條引用路徑可及性判斷:在這條路徑中,最弱的一個引用決定對象的可及性。 
◆多條引用路徑可及性判斷:幾條路徑中,最強的一條的引用決定對象的可及性。 
    比如,我們假設圖2中引用①和③爲強引用,⑤爲軟引用,⑦爲弱引用,對於對象5按照這兩個判斷原則,路徑①-⑤取最弱的引用⑤,因此該路徑對對象5的引用爲軟引用。同樣,③-⑦爲弱引用。在這兩條路徑之間取最強的引用,於是對象5是一個軟可及對象。 
3.使用軟引用構建敏感數據的緩存 
3.1 爲什麼需要使用軟引用 
   首先,我們看一個僱員信息查詢系統的實例。我們將使用一個Java語言實現的僱員信息查詢系統查詢存儲在磁盤文件或者數據庫中的僱員人事檔案信息。作爲一個用戶,我們完全有可能需要回頭去查看幾分鐘甚至幾秒鐘前查看過的僱員檔案信息(同樣,我們在瀏覽WEB頁面的時候也經常會使用“後退”按鈕)。這時我們通常會有兩種程序實現方式:一種是把過去查看過的僱員信息保存在內存中,每一個存儲了僱員檔案信息的Java對象的生命週期貫穿整個應用程序始終;另一種是當用戶開始查看其他僱員的檔案信息的時候,把存儲了當前所查看的僱員檔案信息的Java對象結束引用,使得垃圾收集線程可以回收其所佔用的內存空間,當用戶再次需要瀏覽該僱員的檔案信息的時候,重新構建該僱員的信息。很顯然,第一種實現方法將造成大量的內存浪費,而第二種實現的缺陷在於即使垃圾收集線程還沒有進行垃圾收集,包含僱員檔案信息的對象仍然完好地保存在內存中,應用程序也要重新構建一個對象。我們知道,訪問磁盤文件、訪問網絡資源、查詢數據庫等操作都是影響應用程序執行性能的重要因素,如果能重新獲取那些尚未被回收的Java對象的引用,必將減少不必要的訪問,大大提高程序的運行速度。 

3.2 如果使用軟引用 
SoftReference的特點是它的一個實例保存對一個Java對象的軟引用,該軟引用的存在不妨礙垃圾收集線程對該Java對象的回收。也就是說,一旦SoftReference保存了對一個Java對象的軟引用後,在垃圾線程對這個Java對象回收前,SoftReference類所提供的get()方法返回Java對象的強引用。另外,一旦垃圾線程回收該Java對象之後,get()方法將返回null。 
看下面代碼: 

Java代碼  收藏代碼
  1. MyObject aRef = new  MyObject();  
  2. SoftReference aSoftRef=new SoftReference(aRef);  


    此時,對於這個MyObject對象,有兩個引用路徑,一個是來自SoftReference對象的軟引用,一個來自變量aReference的強引用,所以這個MyObject對象是強可及對象。 
隨即,我們可以結束aReference對這個MyObject實例的強引用: 
aRef = null; 
此後,這個MyObject對象成爲了軟可及對象。如果垃圾收集線程進行內存垃圾收集,並不會因爲有一個SoftReference對該對象的引用而始終保留該對象。Java虛擬機的垃圾收集線程對軟可及對象和其他一般Java對象進行了區別對待:軟可及對象的清理是由垃圾收集線程根據其特定算法按照內存需求決定的。也就是說,垃圾收集線程會在虛擬機拋出OutOfMemoryError之前回收軟可及對象,而且虛擬機會儘可能優先回收長時間閒置不用的軟可及對象,對那些剛剛構建的或剛剛使用過的“新”軟可反對象會被虛擬機儘可能保留。在回收這些對象之前,我們可以通過: 
Java代碼  收藏代碼
  1. MyObject anotherRef=(MyObject)aSoftRef.get();  

    重新獲得對該實例的強引用。而回收之後,調用get()方法就只能得到null了。 

3.3 使用ReferenceQueue清除失去了軟引用對象的SoftReference 
作爲一個Java對象,SoftReference對象除了具有保存軟引用的特殊性之外,也具有Java對象的一般性。所以,當軟可及對象被回收之後,雖然這個SoftReference對象的get()方法返回null,但這個SoftReference對象已經不再具有存在的價值,需要一個適當的清除機制,避免大量SoftReference對象帶來的內存泄漏。在java.lang.ref包裏還提供了ReferenceQueue。如果在創建SoftReference對象的時候,使用了一個ReferenceQueue對象作爲參數提供給SoftReference的構造方法,如: 
ReferenceQueue queue = new  ReferenceQueue(); 
SoftReference  ref=new  SoftReference(aMyObject, queue); 
    那麼當這個SoftReference所軟引用的aMyOhject被垃圾收集器回收的同時,ref所強引用的SoftReference對象被列入ReferenceQueue。也就是說,ReferenceQueue中保存的對象是Reference對象,而且是已經失去了它所軟引用的對象的Reference對象。另外從ReferenceQueue這個名字也可以看出,它是一個隊列,當我們調用它的poll()方法的時候,如果這個隊列中不是空隊列,那麼將返回隊列前面的那個Reference對象。 
在任何時候,我們都可以調用ReferenceQueue的poll()方法來檢查是否有它所關心的非強可及對象被回收。如果隊列爲空,將返回一個null,否則該方法返回隊列中前面的一個Reference對象。利用這個方法,我們可以檢查哪個SoftReference所軟引用的對象已經被回收。於是我們可以把這些失去所軟引用的對象的SoftReference對象清除掉。常用的方式爲: 
Java代碼  收藏代碼
  1. SoftReference ref = null;  
  2. while ((ref = (EmployeeRef) q.poll()) != null) {  
  3.     // 清除ref  
  4. }  

理解了ReferenceQueue的工作機制之後,我們就可以開始構造一個Java對象的高速緩存器了。 

3.4通過軟可及對象重獲方法實現Java對象的高速緩存 
    利用Java2平臺垃圾收集機制的特性以及前述的垃圾對象重獲方法,我們通過一個僱員信息查詢系統的小例子來說明如何構建一種高速緩存器來避免重複構建同一個對象帶來的性能損失。我們將一個僱員的檔案信息定義爲一個Employee類: 
Java代碼  收藏代碼
  1. public class Employee {  
  2.     private String id;// 僱員的標識號碼  
  3.     private String name;// 僱員姓名  
  4.     private String department;// 該僱員所在部門  
  5.     private String Phone;// 該僱員聯繫電話  
  6.     private int salary;// 該僱員薪資  
  7.     private String origin;// 該僱員信息的來源  
  8.    
  9.     // 構造方法  
  10.     public Employee(String id) {  
  11.        this.id = id;  
  12.        getDataFromlnfoCenter();  
  13.     }  
  14.    
  15.     // 到數據庫中取得僱員信息  
  16.     private void getDataFromlnfoCenter() {  
  17.        // 和數據庫建立連接井查詢該僱員的信息,將查詢結果賦值  
  18.        // 給name,department,plone,salary等變量  
  19.        // 同時將origin賦值爲"From DataBase"  
  20.     }  

…… 
這個Employee類的構造方法中我們可以預見,如果每次需要查詢一個僱員的信息。哪怕是幾秒中之前剛剛查詢過的,都要重新構建一個實例,這是需要消耗很多時間的。下面是一個對Employee對象進行緩存的緩存器的定義: 
Java代碼  收藏代碼
  1. import java.lang.ref.ReferenceQueue;  
  2. import java.lang.ref.SoftReference;  
  3. import java.util.Hashtable;  
  4. public class EmployeeCache {  
  5.     static private EmployeeCache cache;// 一個Cache實例  
  6.     private Hashtable<String,EmployeeRef> employeeRefs;// 用於Chche內容的存儲  
  7.     private ReferenceQueue<Employee> q;// 垃圾Reference的隊列  
  8.    
  9.     // 繼承SoftReference,使得每一個實例都具有可識別的標識。  
  10.     // 並且該標識與其在HashMap內的key相同。  
  11.     private class EmployeeRef extends SoftReference<Employee> {  
  12.        private String _key = "";  
  13.    
  14.        public EmployeeRef(Employee em, ReferenceQueue<Employee> q) {  
  15.            super(em, q);  
  16.            _key = em.getID();  
  17.        }  
  18.     }  
  19.    
  20.     // 構建一個緩存器實例  
  21.     private EmployeeCache() {  
  22.        employeeRefs = new Hashtable<String,EmployeeRef>();  
  23.        q = new ReferenceQueue<Employee>();  
  24.     }  
  25.    
  26.     // 取得緩存器實例  
  27.     public static EmployeeCache getInstance() {  
  28.        if (cache == null) {  
  29.            cache = new EmployeeCache();  
  30.        }  
  31.        return cache;  
  32.     }  
  33.    
  34.     // 以軟引用的方式對一個Employee對象的實例進行引用並保存該引用  
  35.     private void cacheEmployee(Employee em) {  
  36.        cleanCache();// 清除垃圾引用  
  37.        EmployeeRef ref = new EmployeeRef(em, q);  
  38.        employeeRefs.put(em.getID(), ref);  
  39.     }  
  40.    
  41.     // 依據所指定的ID號,重新獲取相應Employee對象的實例  
  42.     public Employee getEmployee(String ID) {  
  43.        Employee em = null;  
  44.        // 緩存中是否有該Employee實例的軟引用,如果有,從軟引用中取得。  
  45.        if (employeeRefs.containsKey(ID)) {  
  46.            EmployeeRef ref = (EmployeeRef) employeeRefs.get(ID);  
  47.            em = (Employee) ref.get();  
  48.        }  
  49.        // 如果沒有軟引用,或者從軟引用中得到的實例是null,重新構建一個實例,  
  50.        // 並保存對這個新建實例的軟引用  
  51.        if (em == null) {  
  52.            em = new Employee(ID);  
  53.            System.out.println("Retrieve From EmployeeInfoCenter. ID=" + ID);  
  54.            this.cacheEmployee(em);  
  55.        }  
  56.        return em;  
  57.     }  
  58.    
  59.     // 清除那些所軟引用的Employee對象已經被回收的EmployeeRef對象  
  60.     private void cleanCache() {  
  61.        EmployeeRef ref = null;  
  62.        while ((ref = (EmployeeRef) q.poll()) != null) {  
  63.            employeeRefs.remove(ref._key);  
  64.        }  
  65.     }  

發佈了24 篇原創文章 · 獲贊 10 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章