在不少場景中,爲了控制緩存的大小,系統按照必定的規則清理緩存。FifoCache是先進先出的版本的裝飾器,當向緩存添加數據時,若是緩存數已經達到上限,則會刪除最老的緩存項。java
下面介紹一下FifoCache,類圖以下算法
FifiCache和LruCache(下面會介紹)都實現了Cache接口。都起着裝飾器的做用apache
實現代碼以下緩存
package org.apache.ibatis.cache.decorators; import java.util.Deque; import java.util.LinkedList; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; /** * FIFO (first in, first out) cache decorator * * @author Clinton Begin */ public class FifoCache implements Cache { // 被裝飾的Cache對象 private final Cache delegate; // 用於記錄key 進入緩存的前後順序 private Deque<Object> keyList; // 記錄了緩存頁的上限,超過該值須要清理緩存(FIFO) private int size; public FifoCache(Cache delegate) { this.delegate = delegate; this.keyList = new LinkedList<Object>(); this.size = 1024; } @Override public String getId() { return delegate.getId(); } @Override public int getSize() { return delegate.getSize(); } public void setSize(int size) { this.size = size; } @Override public void putObject(Object key, Object value) { // 檢測並清理緩存 cycleKeyList(key); delegate.putObject(key, value); } @Override public Object getObject(Object key) { return delegate.getObject(key); } @Override public Object removeObject(Object key) { return delegate.removeObject(key); } @Override public void clear() { delegate.clear(); keyList.clear(); } @Override public ReadWriteLock getReadWriteLock() { return null; } private void cycleKeyList(Object key) { // 把key 加入隊列 keyList.addLast(key); if (keyList.size() > size) { // 獲取隊列的第一個key ,而且從隊列中刪除 Object oldestKey = keyList.removeFirst(); // 從HashMap 中刪除 緩存項 delegate.removeObject(oldestKey); } } }
LruCache 是按照LRU 算法進行緩存清理的裝飾器,在須要清理緩存時,它會清除最近最少使用的緩存項。ide
實現代碼以下this
package org.apache.ibatis.cache.decorators; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; /** * Lru (least recently used) cache decorator * * @author Clinton Begin */ public class LruCache implements Cache { // 被裝飾的對象 private final Cache delegate; //new LinkedHashMap<Object, Object>(size, .75F, true) 有序的map ,用於記錄key最近使用的狀況 private Map<Object, Object> keyMap; // 記錄最少被使用的緩存項key private Object eldestKey; public LruCache(Cache delegate) { this.delegate = delegate; setSize(1024); } @Override public String getId() { return delegate.getId(); } @Override public int getSize() { return delegate.getSize(); } /** **從新設置緩存的大小,會重置KeyMap 字段 **/ public void setSize(final int size) { keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) { private static final long serialVersionUID = 4267176411845948333L; @Override protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) { // 若是到達上限 則更新eldestKey boolean tooBig = size() > size; if (tooBig) { eldestKey = eldest.getKey(); } return tooBig; } }; } @Override public void putObject(Object key, Object value) { delegate.putObject(key, value); // 刪除最近未使用的key cycleKeyList(key); } @Override public Object getObject(Object key) { // 修改linkedHashMap 中記錄的順序 keyMap.get(key); return delegate.getObject(key); } @Override public Object removeObject(Object key) { return delegate.removeObject(key); } @Override public void clear() { delegate.clear(); keyMap.clear(); } @Override public ReadWriteLock getReadWriteLock() { return null; } private void cycleKeyList(Object key) { keyMap.put(key, key); if (eldestKey != null) { delegate.removeObject(eldestKey); eldestKey = null; } } }