实现
通过重写 LinkedHashMap.removeEldestEntry 方法可以实现一个最简单的具有淘汰机制的缓存。
class LRUHashMap<K, V> extends LinkedHashMap<K, V>{
private final int maximumSize;
public LRUHashMap(int maximumSize) {
super(maximumSize);
this.maximumSize = maximumSize;
}
/**
* 该方法会在put时候调用,如果为true,删除最老的Item
* @param eldest 最老的Item
* @return 是否删除
*/
@Override
protected boolean removeEldestEntry(Entry eldest) {
return size() > maximumSize;
}
public synchronized V getValue(K key) {
return get(key);
}
public synchronized void putValue(K key, V value) {
put(key, value);
}
public synchronized V removeValue(K key) {
return remove(key);
}
}
使用方式
LRUHashMap<String, Object> lruMap = new LRUHashMap<>(10);
for (int i = 1; i <= 11; i++) {
lruMap.put(String.valueOf(i), "val-" + i);
}
System.out.println(lruMap);
LRU(最近最少被使用)
LRU 是常见的缓存淘汰算法之一。LRU 的核心思想是基于 “如果数据最近被访问过,它在未来也极有可能访问过” 。同样把缓存看成一个队列,访问一个数据时,如果缓存中不存在,则插入到队列尾部;如果缓存中存在,则把该数据移动到队列尾部。当执行淘汰操作时,同样从队列的头部开始淘汰。
如下图:
当有热点数据时,LRU算法效率很好,可以保持热点数据不被淘汰。但是依然有个问题,如果有个数据在1个小时的前59分钟访问了1万次(可见这是个热点数据),再后一分钟没有访问这个数据,但是有其他的数据访问,就会导致了我们这个热点数据被淘汰。