2010-07-24 36 views

回答

2

這聽起來更像你要找的flyweight pattern

Flyweight是一種軟件設計模式。輕量級是通過與其他類似對象共享盡可能多的數據來儘可能減少內存使用的對象

單擊鏈接,它包含一個Java示例。

+0

+1。我認爲這些都是相同的模式(或者一個享元只是一個Interner的一個應用程序),但我更喜歡「享元」,因爲它更容易谷歌 – finnw 2010-07-24 10:07:23

5

事情是這樣的:

public class InternPool<T> { 

    private WeakHashMap<T, WeakReference<T>> pool = 
     new WeakHashMap<T, WeakReference<T>>(); 

    public synchronized T intern(T object) { 
     T res = null; 
     // (The loop is needed to deal with race 
     // conditions where the GC runs while we are 
     // accessing the 'pool' map or the 'ref' object.) 
     do { 
      WeakReference<T> ref = pool.get(object); 
      if (ref == null) { 
       ref = new WeakReference<T>(object); 
       pool.put(object, ref); 
       res = object; 
      } else { 
       res = ref.get(); 
      } 
     } while (res == null); 
     return res; 
    } 
} 

這取決於實施equalshashCode提供「按價值平等」,並服從對這些方法的API合同池元素類。但是BigDecimal當然會。


UPDATE - 對於爲什麼我們需要一個WeakHashMap<T, WeakReference<T>>而非WeakHashMap<T, T>,看到的解釋。簡短的版本是後者中的關鍵弱鏈接不會被GC破壞,因爲相應的條目引用使得這些值可以被高度訪問。

+0

我假設你不需要檢查ref.get()是空值。 – 2010-07-24 07:58:48

+0

我認爲不是,但我意識到GC存在競爭條件。如果GC在調用get後立即運行,那麼當我們查看它時,返回的'ref'可能會被破壞。整件事情需要循環。更新。 – 2010-07-24 09:03:43

+0

爲什麼你需要一個WeakReference作爲地圖值?您是不是已經在使用WeakhashMap,所以如果沒有對該對象的強引用,該條目將被刪除? – as3rdaccount 2014-02-26 14:50:43

4

舉個例子,看看InternerGuava。它的確不是而是需要一個Internable接口,它只依賴於equalshashCode

3

我將會分離解決方案分爲兩大類,以提供更簡潔的代碼,同時也通過這種方式擺脫循環:

public class WeakPool<T> { 
    private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>(); 
    public T get(T object) { 
     final T res; 
     WeakReference<T> ref = pool.get(object); 
     if (ref != null) { 
      res = ref.get(); 
     } else { 
      res = null; 
     } 
     return res; 
    } 
    public void put(T object) { 
     pool.put(object, new WeakReference<T>(object)); 
    } 
} 

和使用弱池實習類是非常簡單的:

public class InternPool<T> { 

    private final WeakPool<T> pool = new WeakPool<T>(); 

    public synchronized T intern(T object) { 
     T res = pool.get(object); 
     if (res == null) { 
      pool.put(object); 
      res = object; 
     } 
     return res; 
    } 
} 
1

只是一個快速警告:

它並沒有明確提到上面,但它應該是顯而易見的,被禁止的對象必須屬於不可變的類型。

第二個注意事項:您不需要使用另一個對象的弱引用作爲地圖中的值,如果您只依靠地圖的鍵集來訪問數據,則對靜態的引用就足夠了。例如,聲明:

WeakHashMap<T,Boolean> 

而且插入對爲:

pool.put (object, Boolean.TRUE); 

這是一個WeakReference的實例的未成年人儲蓄(如果您不能重複使用的關鍵之一)。

...或者創建一個WeakSet類,就像@PeterVerhas用他的WeakPool所做的那樣。

+0

所以用你的方法如何檢索一個對象的實習生表示?迭代所有的鍵和檢查相等? – Sergio 2015-08-07 17:42:40

0

不應該

「WeakReference ref = pool.get(object);」

改爲

WeakReference ref = pool.intern(object);

??

+0

對不起,我的評論 – FrederikH 2015-09-10 15:50:04