在開始閱讀這篇博文前,需要一點點java基礎的儲備知識
1.ReferenceQueue的作用,我上一篇博文有比較深入的講解。
2.簡單瞭解LRU演算法,我在這裡推薦兩篇快速瞭解並學習LRU演算法的博文連結:
http://blog.csdn.net/Ackarlix/archive/2007/08/26/1759793.aspx
http://liangwj72.iteye.com/blog/123856
直接上代碼
package cn.itcast.camera.gallery;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* LruCache(對象緩衝池)用於緩衝對象,有些圖片或者視頻在介面上顯示,如果每次都從資料庫去取(圖片或視頻檔案以二進位流的形式存在資料庫中),
* 就會加應用處理的負擔
* ,用LruCache就能解決此問題,只要第一次從資料庫中取出,然後把取出的東西放在LRUCache中,之後每次就可以從LRUCache中去取了
* ,加快訪問速度。並有效地節省記憶體。
*/
public class LruCache<K, V> {
//mLruMap:一個簡單實現LRU演算法的LinkedHashMap
private final HashMap<K, V> mLruMap;
//mWeakMap:儲存 弱引用對象Entry
private final HashMap<K, Entry<K, V>> mWeakMap = new HashMap<K, Entry<K, V>>();
//mQueue:記錄引用對象已被記憶體回收行程回收過的Entry
private ReferenceQueue<V> mQueue = new ReferenceQueue<V>();
//設定LruCache固定儲存的最大容量
@SuppressWarnings("serial")
public LruCache(final int capacity) {
mLruMap = new LinkedHashMap<K, V>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
//LRU演算法最關鍵的一步,自動清除到期資料,始終保證mLruMap 的size<=capacity,即mLruMap 記憶體佔用總大小<=單個對象所佔記憶體*capacity
return size() > capacity;
}
};
}
private static class Entry<K, V> extends WeakReference<V> {
//儲存Key值,以便mWeakMap刪除已被記憶體回收行程回收過的弱引用對象Entry
K mKey;
public Entry(K key, V value, ReferenceQueue<V> queue) {
super(value, queue);
mKey = key;
}
}
//清空mWeakMap裡已被記憶體回收行程回收過的Entry(表明Entry所引用的對象已經被記憶體回收行程回收,這時需要清除Entry對象本身)
@SuppressWarnings("unchecked")
private void cleanUpWeakMap() {
Entry<K, V> entry = (Entry<K, V>) mQueue.poll();
//一旦記憶體回收行程回收該Entry所引用的對象,就從mWeakMap裡刪除該Entry
while (entry != null) {
mWeakMap.remove(entry.mKey);
entry = (Entry<K, V>) mQueue.poll();
}
}
//將對象放入緩衝,並儲存弱引用
public synchronized V put(K key, V value) {
cleanUpWeakMap();
mLruMap.put(key, value);
Entry<K, V> entry = mWeakMap.put(key, new Entry<K, V>(key, value, mQueue));
return entry == null ? null : entry.get();
}
//取得對象
public synchronized V get(K key) {
cleanUpWeakMap();
V value = mLruMap.get(key);
if (value != null)
return value;
Entry<K, V> entry = mWeakMap.get(key);
return entry == null ? null : entry.get();
}
//清空
public synchronized void clear() {
mLruMap.clear();
mWeakMap.clear();
mQueue = new ReferenceQueue<V>();
}
}