【Java】LRU缓存结构及其请求页存储管理的使用

首先让我们看一道题:

在一个请求页式存储管理中,一个程序的页面走向为 4, 3, 2, 1, 3, 5, 4, 3, 2, 1, 5,并采用 LRU 算法。假设分配给该程序的存储块个数 M 分别为 3 和 4,则该访问中发生的缺页次数 F 分别是?

这里我们讲讲两个概念:
请求分页存储管理:
在进程开始前,仅装入当前要执行的部分页面即可执行;在执行过程中,可使用请求调入中断动态装入要访问但又不存在的页面;当内存空间已满,而又需要装入新的页面时,可根据置换功能适当调出页面,以便腾出空间装新的页面。
LRU算法:
Least Recently Used,及最近最久未使用

也就是说,例如在请求分页中,使用LRU管理,当内存空间已满时,就可调用算法淘汰最近一段时间内最长时间未被使用的页面。
一般建议使用双向链表+HashMap实现本算法。

先用最近常考的一道笔试题来简单实现LRU的缓存结构
上个牛客链接
代码:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
//基本思路 使用Hashmap+双向链表实现
//最近使用(进行了set/get操作)放在表头
//空间超过时,删除尾部元素
public class LRUCache {
    //本代码通过80%

    private int k;
    private DNode head=new DNode(-1,-1);
    private DNode tail=new DNode(-1,-1);
    private Map<Integer,DNode> map=new HashMap<>();

    public int[] LRU (int[][] operators, int k) {
        this.k=k;
        //链表勾连初始化
        head.next=tail;
        tail.prev=head;
        //opt首元素为2的个数
        int len = (int) Arrays.stream(operators).filter(x -> x[0] == 2).count();
        int []res=new int[len];
        for(int i=0,j=0;i<operators.length;i++){
            if(operators[i][0]==1){//opt=1
                set(operators[i][1],operators[i][2]);
            }else {//opt=2
                res[j++]=get(operators[i][1]);
            }
        }
        return res;
    }
    private void set(int key,int val){
        //先检测原key是否有值
        DNode node=map.get(key);
        if (node==null){
            if(map.size()==k){
                DNode tailnode=popTail();//拉队尾元素
                map.remove(tailnode.key);

            }
            DNode newNode=new DNode(key,val);
            map.put(key,newNode);
            addNode(newNode);
        }else {
            node.val=val;
            moveToHead(node);
        }
    }
    private int get(int key){
        if(map.containsKey(key)){
            DNode node=map.get(key);
            moveToHead(node);
            return node.val;
        }
        return -1;
    }
    //头节点加入
    public void addNode(DNode node){
        node.prev=head;
        node.next=head.next;
        head.next.prev=node;
        head.next=node;
    }

    //删除
    //将当前结点的前后指针接在一起
    public void removeNode(DNode node){
        DNode prev=node.prev;
        DNode next=node.next;
        prev.next=next;
        next.prev=prev;
    }
    //
    private void moveToHead(DNode node){
        removeNode(node);//将原结点前后指针接在一起
        addNode(node);//表头添加
    }
    private DNode popTail(){
        DNode res=tail.prev;
        removeNode(res);
        return res;
    }


    //双向链表
    static class DNode{
        DNode prev;
        DNode next;
        int val;
        int key;

        public DNode() {
        }

        public DNode(int val, int key) {
            this.val = val;
            this.key = key;
        }
    }

    public static void main(String[] args) {
        int[][] operators = {{1, 2, 1}, {1, 2, 2}, {1, 3, 2}, {2, 1}, {1, 4, 4}, {2, 2}};
        int len = (int) Arrays.stream(operators).filter(x -> x[0] == 2).count();
        System.out.println(len);
    }
}

现在回头继续看那道选择题

一个程序的页面走向为 4, 3, 2, 1, 3, 5, 4, 3, 2, 1, 5,并采用 LRU 算法。假设分配给该程序的存储块个数 M 分别为 3 和 4,则该访问中发生的缺页次数 F 分别是?

M=3

请求分页管理    缺页
 4          1
 34         1
 234           1
 123        1
 312        0
 531        1
 453       1
 345        0
 234       1 
 123      1
 512      1

F=9
M=4时同理判断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值