LRU是Least Recently Used 近期最少使用算法
1. 原理
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。涉及到操作系统原理的部分知识。
使用两种数据结构实现LRU Cache
- Queue: 是由双向链表实现的,队列的容量等于缓存的大小,最近使用的页在前端,最少使用的页在后端。队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
- Hash:page number as key and address of the corresponding queue node as value.
引用页面(page)时,所需页面可能位于内存中。 如果它在内存中,我们需要分离列表的节点并将其带到队列的前面。
如果所需页面不在内存中,我们将其带入内存。 简单来说,我们在队列的前面添加一个新节点,并更新哈希中相应的节点地址。 如果队列已满,即所有页框(page frame)都已满,我们从队列后面删除一个节点,并将新节点添加到队列的前面。
例子如下:
有一个字符串:
1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5
有3个页槽(page frame),找到页面错误(page faults)的数量。
注意:一开始内存为空。
算法如下:
**
* @Author: HASEE
* @Description: LRU算法
* @Date: Created in 17:17 2019/3/5
* @Modified By:
*/
public class LRUCache {
/**
* We can use Java inbuilt Deque as a double ended queue to store the cache keys,
* with the descending time of reference from front to back and a set container
* to check presence of a key. But remove a key from the Deque using remove(),
* it takes O(N) time. This can be optimized by storing a reference (iterator)
* to each key in a hash map.
*/
// store key of cache
static Deque<Integer> deque;
// store references of key in cache
static HashSet<Integer> map;
// maximum capacity of cache
static int csize;
LRUCache(int n) {
deque = new LinkedList<>();
map = new HashSet<>();
csize = n;
}
// Refers key x with in the LRU cache
public void refer(int x) {
if (!map.contains(x)) {
if (deque.size() == csize) {
int last = deque.removeLast();
map.remove(last);
}
} else {
/* The found page may not be always the last element, even if it's an
intermediate element that needs to be removed and added to the start
of the Queue */
int index = 0, i = 0;
Iterator<Integer> itr = deque.iterator();
while (itr.hasNext()) {
if (itr.next() == x) {
index = i;
break;
}
i++;
}
deque.remove(index);
}
deque.push(x);
map.add(x);
}
// display contents of cache
public void display() {
Iterator<Integer> itr = deque.iterator();
while(itr.hasNext()){
System.out.print(itr.next() + " ");
}
}
public static void main(String[] args) {
LRUCache ca=new LRUCache(4);
ca.refer(1);
ca.refer(2);
ca.refer(3);
ca.refer(1);
ca.refer(4);
ca.refer(5);
ca.display();
}
}
结果:
5 4 1 3
以上只是简单的描述LRU的原理。
常见的改进算法有:LRU-K、Two queues(2Q)、Multi Queue(MQ)等。
有关他们的具体比较。请参考:https://www.cnblogs.com/work115/p/5585341.html
https://www.cnblogs.com/work115/p/5585341.html
转载:
https://www.geeksforgeeks.org/lru-cache-implementation/