閑來無事,用Java的軟引用寫了一個山寨的緩衝

來源:互聯網
上載者:User

標籤:

閑來無事,用Java的軟引用寫了一個山寨的緩衝 部落格分類:
  • java基礎
眾所周知java中的引用分為 StrongReference、SoftReference、WeakReference、PhantomReference。這幾種引用有不同那個的 使用情境,平時我們用的最頻繁的也就是StrongReference也就是說形如之這樣的引用:

 

Object obj = new Object();

  這種引用就是所謂的強引用,如果此對象沒有引用指向它,並且活著的線程無法訪問到它(針對垃圾孤島而言),那麼他才會被回收,如果該對象被強引用指向,並且記憶體被耗盡,拋出OOM垃圾收集器也不會回收該對象。

而對於SoftReference而言它被GC回收的條件就沒 那麼嚴格了,如果一個對象當前最強的引用是軟引用,並且JVM的記憶體充足,記憶體回收行程是不會回收的該對象的。只有在記憶體比較吃緊的情況下GC才會回收被軟 引用指向的對象,從這個特點我們就看出了軟引用可以用來做一些快取,配合LRU策略更好。今天我就自己寫一個玩玩。

 

Java代碼  
  1. 代碼如下:  
Java代碼  
  1. package com.blackbeans.example;  
  2.   
  3. import java.lang.ref.Reference;  
  4. import java.lang.ref.ReferenceQueue;  
  5. import java.lang.ref.SoftReference;  
  6. import java.util.HashMap;  
  7.   
  8. /** 
  9.  *  
  10.  * @author blackbeans 
  11.  * @param <K> 
  12.  * @param <T> 
  13.  */  
  14. public class ReferenceCache<K,T> {  
  15.       
  16.       
  17.     private HashMap<K, InnerReference<K,T>>  cachedReference = new HashMap<K, InnerReference<K,T>>(1024);  
  18.     private final  ReferenceQueue<T>  referenceQueue ;  
  19.       
  20.     private final ObjectNotFoundHandler<K,T> existsHandler;  
  21.       
  22.     /** 
  23.      * 預設緩衝中取不到時的處理器 
  24.      * @author blackbeans 
  25.      * 
  26.      * @param <K> 
  27.      * @param <T> 
  28.      */  
  29.     private static class DefaultObjectNotFoundHandler<K,T> implements ObjectNotFoundHandler<K,T>  
  30.     {  
  31.         @Override  
  32.         public T queryAndCached(K key) {  
  33.             // TODO Auto-generated method stub  
  34.             return null;  
  35.         }  
  36.           
  37.     }  
  38.       
  39.     /** 
  40.      * 緩衝中取不到時的處理器 
  41.      * @author blackbeans 
  42.      * 
  43.      * @param <K> 
  44.      * @param <T> 
  45.      */  
  46.     public static interface ObjectNotFoundHandler<K,T>  
  47.     {  
  48.         public T queryAndCached(K key);  
  49.           
  50.     }  
  51.       
  52.       
  53.     private static class InnerReference<K,T> extends SoftReference<T>{  
  54.         private final K key ;  
  55.         public InnerReference(K key,T reference,ReferenceQueue<T> queue) {  
  56.             super(reference,queue);  
  57.             this.key = key;  
  58.         }  
  59.           
  60.         public K getKey()  
  61.         {  
  62.             return this.key;  
  63.         }  
  64.     }   
  65.       
  66.       
  67.     public ReferenceCache(ObjectNotFoundHandler<K,T> handler)  
  68.     {  
  69.         this.referenceQueue = new ReferenceQueue<T>();  
  70.         this.existsHandler = handler == null ? new DefaultObjectNotFoundHandler<K,T>() : handler;  
  71.     }  
  72.       
  73.       
  74.     public ReferenceCache()  
  75.     {  
  76.         this(null);  
  77.     }  
  78.       
  79.     public void cachedReference(K key,T reference)  
  80.     {  
  81.         /** 
  82.          * 清除被軟引用的對象並已經被回收的reference 
  83.          */  
  84.         cleanReference(key);  
  85.         if(!this.cachedReference.containsKey(key))  
  86.         {  
  87.             this.cachedReference.put(key, new InnerReference<K,T>(key,reference, this.referenceQueue));  
  88.         }  
  89.     }  
  90.       
  91.     public T getReference(K key)    {  
  92.           
  93.         T obj = null;  
  94.           
  95.         if(this.cachedReference.containsKey(key)){  
  96.             obj =  this.cachedReference.get(key).get();  
  97.         }  
  98.           
  99.         if(null == obj)  
  100.         {  
  101.             /** 
  102.              * 軟引用指向的對象被回收,並緩衝該軟引用 
  103.              */  
  104.             obj = this.existsHandler.queryAndCached(key);  
  105.             this.cachedReference(key, obj);  
  106.             return obj;  
  107.         }  
  108.         return obj;  
  109.           
  110.     }  
  111.   
  112.     @SuppressWarnings("unchecked")  
  113.     private void cleanReference(K key) {  
  114.         //優先檢查key對應軟引用的對象是否被回收  
  115.         if (this.cachedReference.containsKey(key)  
  116.                 && this.cachedReference.get(key).get() == null)  
  117.             this.cachedReference.remove(key);  
Java代碼  
  1. <span style="white-space: pre;">        </span>T obj = null;  
  2.         //如果當前Key對應的軟引用的對象被回收則移除該Key  
  3.         Reference<? extends T> reference = null;  
  4.         while((reference = this.referenceQueue.poll()) != null)  
  5.         {  
  6.             obj = reference.get();  
  7.             if(obj == null)  
  8.             {  
  9.                 this.cachedReference.remove(((InnerReference<K, T>)reference).getKey());  
  10.             }  
  11.         }  
  12.     }  
  13.       
  14.       
  15.     public void clearALLObject()  
  16.     {  
  17.         this.cachedReference.clear();  
  18.         System.gc();  
  19.     }  
  20.       
  21. }  
 

   在整個實現中通過將對象的引用放入我定義的一個 key->軟引用map中,然後每次從cache中擷取對象時,首先通過key去查詢map獲得對象的軟引用,若存在則通過軟引用去嘗試擷取對象, 若不存在,軟引用指向的對象被回收,那麼我們就回去調用內建的handler,重建一個對象,並cache該對象的軟引用。

在我的實現中我為使用者提供了一個當對象被回收時的處理handler,企圖來指導使用者通過這個handler來重新構造對象,緩衝對象,靈活性還是挺大的。

不足之處就是,如果軟引用的緩衝能用LRU策略更完美了,再為 LRU提供一個Processor,用於使用者自訂LRU策略。其實很簡單只要將HashMap換成LinkedHashMap去實現 removeEldest方法,並在方法中調用自訂的LRU處理器就OK了。

        為了減少開銷,我在每次cache的時候才去清理已經失效的軟引用。也許有人會問為啥有個ReferenceQueue呢?其實是這樣的,在軟引用所引用 的對象被回收以後,試想想對象軟引用的對象是被回收了,但是你又引入了另一個對象SoftReference,帶走一個難道還要再留下一個,所以不會的, 軟引用對象被回收後,這個軟引用本身被添加到了這個queue,等待回收。通過便利這個queue擷取軟引用來一出map中到期的軟引用。

至此,該說的也都說了,不該說的也說了,結尾很突兀,敬請見諒!

 

轉載:http://blackbeans.iteye.com/blog/1039464

閑來無事,用Java的軟引用寫了一個山寨的緩衝

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.