package com.xiaoleilu.hutool.cache.impl; import java.util.Iterator; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.xiaoleilu.hutool.cache.Cache; /** * 超时和限制大小的缓存的默认实现<br> * 继承此抽象缓存需要:<br> * <ul> * <li>创建一个新的Map</li> * <li>实现 <code>prune</code> 策略</li> * </ul> * * @author Looly,jodd * * @param <K> 键类型 * @param <V> 值类型 */ public abstract class AbstractCache<K, V> implements Cache<K, V>, Iterable<V>{ protected Map<K, CacheObj<K, V>> cacheMap; private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); private final Lock readLock = cacheLock.readLock(); private final Lock writeLock = cacheLock.writeLock(); /** 返回缓存容量,<code>0</code>表示无大小限制 */ protected int capacity; /** 缓存失效时长, <code>0</code> 表示没有设置 */ protected long timeout; /** 每个对象是否有单独的失效时长,用于决定清理过期对象是否有必要。 */ protected boolean existCustomTimeout; /** 命中数 */ protected int hitCount; /** 丢失数 */ protected int missCount; // ---------------------------------------------------------------- put start @Override public void put(K key, V object) { put(key, object, timeout); } @Override public void put(K key, V object, long timeout) { writeLock.lock(); try { CacheObj<K, V> co = new CacheObj<K, V>(key, object, timeout); if (timeout != 0) { existCustomTimeout = true; } if (isFull()) { pruneCache(); } cacheMap.put(key, co); } finally { writeLock.unlock(); } } // ---------------------------------------------------------------- put end // ---------------------------------------------------------------- get start /** * @return 命中数 */ public int getHitCount() { return hitCount; } /** * @return 丢失数 */ public int getMissCount() { return missCount; } @Override public V get(K key) { readLock.lock(); try { //不存在或已移除 final CacheObj<K, V> co = cacheMap.get(key); if (co == null) { missCount++; return null; } //过期 if (co.isExpired() == true) { // remove(key); // 此方法无法获得锁 cacheMap.remove(key); missCount++; return null; } //命中 hitCount++; return co.get(); } finally { readLock.unlock(); } } // ---------------------------------------------------------------- get end @Override public Iterator<V> iterator() { return new CacheValuesIterator<V>(this); } // ---------------------------------------------------------------- prune start /** * 清理实现 * @return 清理数 */ protected abstract int pruneCache(); @Override public final int prune() { writeLock.lock(); try { return pruneCache(); } finally { writeLock.unlock(); } } // ---------------------------------------------------------------- prune end // ---------------------------------------------------------------- common start @Override public int capacity() { return capacity; } /** * @return 默认缓存失效时长。<br> * 每个对象可以单独设置失效时长 */ @Override public long timeout() { return timeout; } /** * 只有设置公共缓存失效时长或每个对象单独的失效时长时清理可用 * @return 过期对象清理是否可用,内部使用 */ protected boolean isPruneExpiredActive() { return (timeout != 0) || existCustomTimeout; } @Override public boolean isFull() { return (capacity > 0) && (cacheMap.size() >= capacity); } @Override public void remove(K key) { writeLock.lock(); CacheObj<K, V> co; try { co = cacheMap.remove(key); } finally { writeLock.unlock(); } if(null != co){ onRemove(co.key, co.obj); } } @Override public void clear() { writeLock.lock(); try { cacheMap.clear(); } finally { writeLock.unlock(); } } @Override public int size() { return cacheMap.size(); } @Override public boolean isEmpty() { return cacheMap.isEmpty(); } @Override public String toString() { return this.cacheMap.toString(); } // ---------------------------------------------------------------- common end /** * 对象移除回调。默认无动作 * @param key 键 * @param cachedObject 被缓存的对象 */ protected void onRemove(K key, V cachedObject) { } }