LRU原理
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
实现1
最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:
1. 新数据插入到链表头部;
2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
3. 当链表满的时候,将链表尾部的数据丢弃。
分析
【命中率】
当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。
【复杂度】
实现简单。
【代价】
命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。
package com.yifan.permissions
import java.util.concurrent.locks.ReentrantLock
/**
* 类说明:利用LinkedHashMap实现简单的缓存,
* 必须实现removeEldestEntry方法,具体参见JDK文档
*/
class LRULinkedHashMap<K, V> : LinkedHashMap<K, V> {
//最大容量
private val maxCapacity: Int
private val lock = ReentrantLock()
companion object {
const val DEFAULT_LOAD_FACTOR: Float = 0.75f
}
constructor(maxCapacity: Int) : super(maxCapacity, DEFAULT_LOAD_FACTOR, true) {
this.maxCapacity = maxCapacity;
}
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean {
return size > maxCapacity
}
override fun containsKey(key: K): Boolean {
try {
lock.lock();
return super.containsKey(key)
} finally {
lock.unlock()
}
}
override fun get(key: K): V? {
try {
lock.lock()
return super.get(key)
} finally {
lock.unlock()
}
}
override fun put(key: K, value: V): V? {
try {
lock.lock()
return super.put(key, value)
} finally {
lock.unlock()
}
}
override val size: Int
get() = try {
lock.lock()
super.size
} finally {
lock.unlock()
}
override fun clear() {
try {
lock.lock()
super.clear()
} finally {