org.tio.utils.cache.LRUCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mica-net-utils Show documentation
Show all versions of mica-net-utils Show documentation
Mica net is a net framework.
package org.tio.utils.cache;
import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* LRU (least recently used)最近最久未使用缓存
* 根据使用时间来判定对象是否被持续缓存
* 当对象被访问时放入缓存,当缓存满了,最久未被使用的对象将被移除。
* 此缓存基于LinkedHashMap,因此当被缓存的对象每被访问一次,这个对象的key就到链表头部。
* 这个算法简单并且非常快,他比FIFO有一个显著优势是经常使用的对象不太可能被移除缓存。
* 缺点是当缓存满时,不能被很快的访问。
*
* @param 键类型
* @param 值类型
* @author Looly, jodd
*/
public class LRUCache extends ReentrantCache {
private static final long serialVersionUID = 1L;
/**
* 构造
* 默认无超时
*
* @param capacity 容量
*/
public LRUCache(int capacity) {
this(capacity, 0);
}
/**
* 构造
*
* @param capacity 容量
* @param timeout 默认超时时间,单位:毫秒
*/
public LRUCache(int capacity, long timeout) {
this(capacity, timeout, null);
}
/**
* 构造
*
* @param capacity 容量
* @param timeout 默认超时时间,单位:毫秒
* @param listener cache 监听器
*/
public LRUCache(int capacity, long timeout, CacheListener listener) {
super(getCacheMap(capacity, listener), capacity, timeout);
super.setListener(listener);
}
private static Map> getCacheMap(
int capacity, CacheListener listener) {
return new LinkedHashMap>(capacity + 1, .75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry> eldest) {
if (this.size() > capacity) {
if (null != listener) {
CacheObj entry = eldest.getValue();
listener.onRemove(entry.key, entry.obj);
}
return true;
} else {
return false;
}
}
};
}
// ---------------------------------------------------------------- prune
@Override
public AbstractCache setListener(CacheListener listener) {
throw new IllegalArgumentException("请使用构造方法添加 CacheListener 参数");
}
/**
* 只清理超时对象,LRU的实现会交给{@code LinkedHashMap}
*/
@Override
protected int pruneCache() {
if (!isPruneExpiredActive()) {
return 0;
}
int count = 0;
Iterator> values = cacheObjIter();
CacheObj co;
while (values.hasNext()) {
co = values.next();
if (co.isExpired()) {
values.remove();
onRemove(co.key, co.obj);
count++;
}
}
return count;
}
}