在不少场景中,为了控制缓存的大小,系统按照必定的规则清理缓存。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; } } }