一次LRU算法的应用及实现

概述

  • 最近刚好有个述求是希望实时维护社区最常被访问的达人列表作为推荐数据源,前置流程我通过Redis里的HyperLogLog已经计算了各达人主页的PV、UV,故只剩下一个类似LRU机制的达人列表要持久化维护了
  • 复习下LRU的原理:LRU原理及实现

实现

  • 可以基于HashMap及LinkedList自己手写,也可以通过继承LinkedHashMap来设计,这里给出两种简单的实现方案:
public class LRUCache {

    /**
     * 基于HashMap记录k-v和数组记录元素访问顺序,数组首元素即为待剔除更新元素
     */
    private Map<Integer, Integer> keys = new HashMap<>();
    private List<Integer> visited = new LinkedList<>();
    private int cap;
    private int num = 0;

    public LRUCache(int capacity) {
        this.cap = capacity;
    }

    public int get(int key) {
        if (!keys.containsKey(key)) {
            return -1;
        }
        visited.remove((Integer)key);
        visited.add(key);
        return keys.get(key);
    }

    public void put(int key, int value) {
        if (keys.containsKey(key)) {
            visited.remove((Integer)key);
        } else if (num < cap) {
            num++;
        } else {
            keys.remove(visited.get(0));
            visited.remove(0);
        }

        keys.put(key, value);
        visited.add(key);
    }
}
private class LRUInnerCache extends LinkedHashMap<Integer, Integer> {

        private int cap;

        LRUInnerCache(int cap) {
            super(cap, 0.75f, true);
            this.cap = cap;
        }

        public int get(int key) {
            Integer value = super.get(key);
            if (value == null) {
                return -1;
            }
            return value;
        }

        public void put(int key, int value) {
            super.put(key, value);
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
            return this.size() > cap;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
页面置换算法是操作系统中常用的一种内存管理算法,主要用于解决内存不足时的页面置换问题。其中,FIFO算法LRU算法、OPT算法是常用的三种页面置换算法。它们分别采用了不同的策略来选择需要被替换的页面。 FIFO算法(First In First Out):是最简单的页面置换算法,它总是选择最早进入内存的页面进行替换。该算法实现比较简单,可以使用一个先进先出队列来维护内存中的页面。当需要进行页面替换时,从队列头部取出最早进入内存的页面进行替换即可。 以下是用C语言实现FIFO算法的代码: ``` #define N 3 // 内存中可以容纳的页面数 int main(){ int page[N] = {0}; // 初始化页面数组 int head = 0; // 页面队列头部 int tail = 0; // 页面队列尾部 int miss = 0; // 缺页次数 int hit = 0; // 命中次数 int pages[] = {1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5}; // 待访问的页面序列 int n = sizeof(pages)/sizeof(int); // 待访问页面序列的长度 for(int i=0; i<n; i++){ int p = pages[i]; int flag = 0; for(int j=0; j<N; j++){ if(page[j] == p){ flag = 1; // 命中 break; } } if(flag == 1){ hit++; }else{ miss++; // 缺页 page[tail] = p; tail = (tail+1)%N; // 更新队列尾部 } } printf("缺页次数:%d\n", miss); printf("命中次数:%d\n", hit); return 0; } ``` LRU算法(Least Recently Used):是一种比较常用的页面置换算法,它基于“最近最少使用”的原则选择需要被替换的页面。该算法维护一个链表来记录页面最近一次被访问的时间。每次需要进行页面替换时,选择链表末尾的页面进行替换。 以下是用C语言实现LRU算法的代码: ``` #define N 3 // 内存中可以容纳的页面数 int main(){ int page[N] = {0}; // 初始化页面数组 int time[N] = {0}; // 初始化时间数组 int miss = 0; // 缺页次数 int hit = 0; // 命中次数 int pages[] = {1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5}; // 待访问的页面序列 int n = sizeof(pages)/sizeof(int); // 待访问页面序列的长度 for(int i=0; i<n; i++){ int p = pages[i]; int flag = 0; for(int j=0; j<N; j++){ if(page[j] == p){ flag = 1; // 命中 time[j] = i+1; // 更新时间戳 break; } } if(flag == 1){ hit++; }else{ miss++; // 缺页 int min_time = time; int min_index = 0; for(int j=1; j<N; j++){ if(time[j] < min_time){ min_time = time[j]; min_index = j; } } page[min_index] = p; // 替换最久未使用的页面 time[min_index] = i+1; // 更新时间戳 } } printf("缺页次数:%d\n", miss); printf("命中次数:%d\n", hit); return 0; } ``` OPT算法(Optimal Page Replacement):是一种理论上最优的页面置换算法,它基于未来访问情况选择需要被替换的页面。该算法需要预测每个页面在未来一段时间内是否会被访问,然后选择在未来最长时间内不会被访问的页面进行替换。由于预测未来访问情况很难做到100%准确,因此该算法在实际应用中较少使用。 以下是用C语言实现OPT算法的代码: ``` #define N 3 // 内存中可以容纳的页面数 int main(){ int page[N] = {0}; // 初始化页面数组 int miss = 0; // 缺页次数 int hit = 0; // 命中次数 int pages[] = {1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5}; // 待访问的页面序列 int n = sizeof(pages)/sizeof(int); // 待访问页面序列的长度 for(int i=0; i<n; i++){ int p = pages[i]; int flag = 0; for(int j=0; j<N; j++){ if(page[j] == p){ flag = 1; // 命中 break; } } if(flag == 1){ hit++; }else{ miss++; // 缺页 int max_index = -1; int max_future = -1; for(int j=0; j<N; j++){ int future = -1; for(int k=i+1; k<n; k++){ if(pages[k] == page[j]){ future = k-i; break; } } if(future == -1){ max_index = j; break; }else{ if(future > max_future){ max_future = future; max_index = j; } } } page[max_index] = p; // 替换最长时间内不会被访问的页面 } } printf("缺页次数:%d\n", miss); printf("命中次数:%d\n", hit); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值