1.问题
LRU是least Recently Used 的缩写,他的意思是“最近最少使用”。LRU缓存就是使用功能这种原理实现的。简单的说,就是缓存一定量的数据,当超过设定阈值时就把一些过期的数据删除掉,常用于页面置换算法,为虚拟页式存储管理中常用的算法、
2 思路分析:
可以使用两个数据结构实现一个LRU缓存。
1)使用双向链表实现的队列。队列的最大容量为缓存的大小,在使用过程中,把最近使用的页面移动到队列头,最近没有使用到的页面放在队列尾的位置。
2)使用一个哈希表,把页号作为建,把缓存在队列中的节点的地址作为值。
当使用一个页面时,所需的页面在内存中。需要把这个页对饮的节点移到队列的前面,如果需要的页面不在内存中,将他存储在内存中。简单的说,就是将一个新的节点添加到队列的前面,并在哈希表中更新相应的节点地址。如果队列是满的,那么就需要从队列尾部移除一个节点,并将新节点添加到队列的前面。
3代码实现
package Queue;
import java.util.ArrayDeque;
import java.util.HashSet;
public class LRU {
private int cacheSize;//队列的最大容量,
private ArrayDeque<Integer> deque=new ArrayDeque<>();//双向链表
private HashSet<Integer> hashSet=new HashSet<>();//哈希表
//构造函数
public LRU(int cacheSize) {
this.cacheSize = cacheSize;
}
//判断链表是否已满
private Boolean isEmpty(){
return deque.size()==cacheSize;
}
//把页号为pageNum的也缓存到队列中,同时也添加到HAsh表中
private void enqueue(int pageNum){
//如果队列满了
if (isEmpty()){
hashSet.remove(deque.getLast());//在哈希表中删除队列最后的那个元素
deque.pollLast();//删除队列最后的那个元素
}
// 把页号为pageNum的缓存加入到队列中
deque.addFirst(pageNum);
//把页号为pageNum的缓存加入到哈希表中
hashSet.add(pageNum);
}
/**
* 当访某一个pageNum时,会调用这个函数,对于访问的page有两种情况
* 1.如果访问的page在缓存队列中,直接把这个节点移动到队首
* 2.如果访问page不在缓存队列中,把这个page添加到队首
*/
public void accessPage(int pageNum){
//page不在队列中,把他缓存到队首
if (!hashSet.contains(pageNum)){
enqueue(pageNum);
}else if (pageNum!=deque.getFirst()){//说明page在队列中,如果page不在队首,将其移动到队首
deque.remove(pageNum);
deque.addFirst(pageNum);
}
}
//打印
void printQueue(){
while (!deque.isEmpty()){
System.out.println(deque.pop()+" ");
}
}
public static void main(String[] args) {
//假设内存大小为3
LRU lru=new LRU(3);
//访问page
lru.accessPage(1);
lru.accessPage(2);
lru.accessPage(5);
lru.accessPage(1);
lru.accessPage(6);
lru.accessPage(7);
//通过上述访问后没缓存的信息为:
lru.printQueue();
}
}