java LRU和LFU缓存置换算法

java实现页面替换算法(LRU、LFU、FIFO) 阅读详情


原文:https://blog.bcmeng.com/post/lru-lfu.html


LRU和LFU缓存置换算法


作者: 康凯森

日期: 2016-05-05

分类: 算法


为什么需要Cache

  • 为了解决俩个存储介质之间的速度不匹配,比如CPU和内存,比如内存和磁盘,比如本地和服务端。
  • 依据程序访问的局部性原理,近期访问的数据,在将来很有可能会被访问

Cache是什么

可以简单认为是一个HashMap,是一个key-value 结构,用来加速访问。

Cache无处不在

缓存的种类:本地服务器缓存、网页缓存、硬盘缓存、一级高速缓存、二级高速缓存等

常用的Cache服务器

  • Memcache
  • Redis

为什么需要 Cache

因为Cache在内存中,所以存储效率高

为什么不全放在 Cache中

  • 内存的数据断电就会丢失
  • Cache比硬盘贵

为什么Cache需要置换

Cache工作原理要求它尽量保存最新数据,但是Cache一般大小有限,当Cache容量达到上限时,就会产生Cache替换的问题。最理想的情况是置换出未来短期内不会被再次访问的数据,但是我们无法预知未来,所以只能从数据在过去的访问情况中寻找规律进行置换。

LFU Cache置换算法

Least Frequently Used algorithm LFU是首先淘汰一定时期内被访问次数最少的页!

这种算法选择近期最少访问的页面作为被替换的页面。显然,这是一种合理的算法,因为到目前为止最少使用的页面,很可能也是将来最少访问的页面。

20150420105345_48639.png-56.1kB

代码如下:

/**
 * Created by kangkaisen on 16/5/4.
 */
import java.util.*;

public class LFUCache {
    private static final int DEFAULT_MAX_SIZE = 3;
    private int capacity = DEFAULT_MAX_SIZE;
    //保存缓存的访问频率和时间
    private final Map<Integer, HitRate> cache = new HashMap<Integer, HitRate>();
    //保存缓存的KV
    private final Map<Integer, Integer> KV = new HashMap<Integer, Integer>();

    // @param capacity, an integer
    public LFUCache(int capacity) {
        this.capacity = capacity;
    }

    // @param key, an integer
    // @param value, an integer
    // @return nothing
    public void set(int key, int value) {
        Integer v = KV.get(key);
        if (v == null) {
            if (cache.size() == capacity) {
                Integer k = getKickedKey();
                KV.remove(k);
                cache.remove(k);
            }
            cache.put(key, new HitRate(key, 1, System.nanoTime()));
        } else { //若是key相同只增加频率,更新时间,并不进行置换
            HitRate hitRate = cache.get(key);
            hitRate.hitCount += 1;
            hitRate.lastTime = System.nanoTime();
        }
        KV.put(key, value);
    }

    public int get(int key) {
        Integer v = KV.get(key);
        if (v != null) {
            HitRate hitRate = cache.get(key);
            hitRate.hitCount += 1;
            hitRate.lastTime = System.nanoTime();
            return v;
        }
        return -1;
    }
    // @return 要被置换的key
    private Integer getKickedKey() {
        HitRate min = Collections.min(cache.values());
        return min.key;
    }

    class HitRate implements Comparable<HitRate> {
        Integer key;
        Integer hitCount; // 命中次数
        Long lastTime; // 上次命中时间

        public HitRate(Integer key, Integer hitCount, Long lastTime) {
            this.key = key;
            this.hitCount = hitCount;
            this.lastTime = lastTime;
        }

        public int compareTo(HitRate o) {
            int hr = hitCount.compareTo(o.hitCount);
            return hr != 0 ? hr : lastTime.compareTo(o.lastTime);
        }
    }

    public static void main(String[] as) throws Exception {
        LFUCache cache = new LFUCache(3);
        cache.set(2, 2);
        cache.set(1, 1);

        System.out.println(cache.get(2));
        System.out.println(cache.get(1));
        System.out.println(cache.get(2));

        cache.set(3, 3);
        cache.set(4, 4);

        System.out.println(cache.get(3));
        System.out.println(cache.get(2));
        System.out.println(cache.get(1));
        System.out.println(cache.get(4));

    }
}

LRU Cache置换算法

Least Recently Used algorithm LRU是首先淘汰最长时间未被使用的页面!

这种算法把近期最久没有被访问过的页面作为被替换的页面。它把LFU算法中要记录数量上的"多"与"少"简化成判断"有"与"无",因此,实现起来比较容易。 屏幕快照 2016-05-05 上午12.33.51.png-123.4kB

代码如下:

import java.util.HashMap;

/**
 * Created by kangkaisen on 16/5/5.
 */

//实现起来比较简单. 维护一个链表,每次数据新添加或者有访问时移动到链表尾,
//每次淘汰数据则是淘汰链表头部的数据.
//也就是最近最少访问的数据在链表头部,最近刚访问的数据在链表尾部    

public class LRUCache {
    private class Node{
        Node prev;
        Node next;
        int key;
        int value;

        public Node(int key, int value) {
            this.key = key;
            this.value = value;
            this.prev = null;
            this.next = null;
        }
    }

    private int capacity;
    private HashMap<Integer, Node> hs = new HashMap<Integer, Node>();
    private Node head = new Node(-1, -1);
    private Node tail = new Node(-1, -1);
    // @param capacity, an integer
    public LRUCache(int capacity) {
        // write your code here
        this.capacity = capacity;
        tail.prev = head;
        head.next = tail;
    }

    // @return an integer
    public int get(int key) {
        // write your code here
        if( !hs.containsKey(key)) {
            return -1;
        }

        // remove current
        Node current = hs.get(key);
        current.prev.next = current.next;
        current.next.prev = current.prev;

        // move current to tail
        move_to_tail(current);

        return hs.get(key).value;


    }

    // @param key, an integer
    // @param value, an integer
    // @return nothing
    public void set(int key, int value) {
        // write your code here
        if( get(key) != -1) {
            hs.get(key).value = value;
            return;
        }

        if (hs.size() == capacity) {
            hs.remove(head.next.key);
            head.next = head.next.next;
            head.next.prev = head;
        }

        Node insert = new Node(key, value);
        hs.put(key, insert);
        move_to_tail(insert);
    }

    private void move_to_tail(Node current) {
        current.prev = tail.prev;
        tail.prev = current;
        current.prev.next = current;
        current.next = tail;
    }

    public static void main(String[] as) throws Exception {
        LRUCache cache = new LRUCache(3);
        cache.set(2, 2);
        cache.set(1, 1);

        System.out.println(cache.get(2));
        System.out.println(cache.get(1));
        System.out.println(cache.get(2));

        cache.set(3, 3);
        cache.set(4, 4);

        System.out.println(cache.get(3));
        System.out.println(cache.get(2));
        System.out.println(cache.get(1));
        System.out.println(cache.get(4));

    }
}

参考资料

九章算法

缓存中的算法-RAND算法,FIFO算法,LFU算法,LRU算法,OPT算法

缓存淘汰算法系列之2——LFU类

缓存淘汰算法 —— LFU-Aging(Java实现) 该算法不正确

LRU和LFU的区别


深入理解分布式技术 - 缓存过期策略&手写LRU 文章目录Pre页面置换算法内存淘汰策略缓存过期策略如何实现一个 LRU 缓存 Pre 缓存使用的是内存资源,而内存资源是非常宝贵的,要用有限的服务器资源支撑更多的业务,就必须让那些访问频率不高的缓存删除掉,为新的缓存腾出内存空间。 这里我们一起来看一下,缓存失效有哪些策略。 页面置换算法 我们从一开始就提到,缓存技术在计算机系统设计中有着非常广泛的应用,对应到操作系统中,就是缓存页面的调度算法。 在操作系统中,文件的读取会先分配一定的页面空间,也就是我们说的 Page,使用页面的时候首先去查询空间是否 阅读详情

相关推荐

LeetCode题解: LRU Cache 缓存设计

设计并实现最近最久未使用的缓存数据结构,支持 get 和 set 操作. get()-如果 key 存在,返回对应的 value 值,否则返回 -1. set()-插入 key 对应的 value 到缓存中,如果缓存已满,将最近最久未使用的元素从缓存中移除。

互联网架构师笔记 1821

LFU算法

1,基本原理LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。LFU的每个数据块都有一个引用计数,所有数据块按照引用计数排序,具有相同引用计数的数据块则按照时间排序。具体实现如下: 1. 新加入数据插入到队列尾部(因为引用计数为1);2. 队列中的数据被访问后,引用计数增加,队列重新排序;3...

Searcher_Recommeder的博客 1万+

告别信号干扰!用Altium Designer 19搞定4层/6层PCB叠层设计的保姆级流程

本文详细介绍了如何使用Altium Designer 19进行4层/6层PCB叠层设计,解决信号干扰问题。通过实际案例和系统方法论,涵盖高速数字电路、混合信号系统等典型场景的设计优化,帮助硬件工程师和学生掌握电磁兼容(EMC)与信号完整性(SI)的核心技术。

weixin_27076351的博客 203

LRU(JAVA简洁版)

一、算法介绍 最近最久未使用(Least Recently Used LRU)算法是⼀种缓存淘汰策略,它是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,发生缺页中断时,将最近一段时间内最久未使用的页面置换出去。 从程序运行的原理来看,最近最久未使用算法是比较接近理想的一种页面置换算法,这种算法既充分利用了内存中页面调用的历史信息,又正确反映了程序的局部问题。 虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,其余页面放入外存的管理方式。 ..

上山的人 1万+

高分辨率航拍图像的目标检测切图优化策略

本文深入探讨了高分辨率航拍图像目标检测中的切图优化策略。针对大尺寸图像直接缩放导致小目标信息丢失的问题,文章详细阐述了基于重叠切割的核心方法,包括如何根据目标尺寸确定切图尺寸与重叠率,并提供了从切图到坐标还原的完整代码实现与避坑指南,有效提升检测精度与效率。

xk7n92h3p5m的博客 1113

昇腾Atlas Duo 300I推理卡实战:从零部署Qwen大模型推理服务

本文详细记录了在华为昇腾Atlas Duo 300I推理卡上,从零部署Qwen1.5-14B-Chat大模型推理服务的完整实战过程。涵盖环境准备、MindIE容器配置、CANN工具链安装、服务启动与API测试等关键步骤,并分享了性能观察与排错经验,为国产AI算力平台部署LLM推理服务提供了实用指南。

weixin_29084231的博客 1233

LRU和LFU 算法(页面置换算法)

LRU和LFU的区别 LRU和LFU都是内存管理的页面置换算法。 LRU:最近最少使用(最长时间)淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的页面。 LFU:最不经常使用(最少次)淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的页面。 例子 假设LFU方法的时期T为10分钟,访问如下页面所花的时间正好为10分钟,内存块大小为3。若所需页面顺序依次如下: 2 1 2 1 2 3 4 ----------

热爱学习和钻研。 4万+

一种导弹追踪算法的MATLAB仿真实现

以下是一个用于模拟机动变轨导弹和防空导弹追踪过程的 MATLAB 代码,同时会提供 3D 效果展示。你可以运行这段代码,从而观察机动变轨导弹和防空导弹的速度与位置变化。

SmartGridequation的博客 933

LRU和LFU算法

在redis的学习中,了解到了两种缓存清理算法,分别是LRU和LFU,在此针对这两种算法进行学习。

qq_43325216的博客 5127

TLSv1.0与TLSv1.1安全漏洞深度解析与实战修复指南

本文深度解析TLSv1.0与TLSv1.1的安全漏洞,包括POODLE和BEAST攻击原理,并提供实战修复指南。通过禁用老旧协议、配置安全加密套件和网络层防护措施,有效提升系统安全性。文章还针对无法立即升级的场景,给出了补偿性防御方案,帮助管理员全面应对传输层安全风险。

weixin_29322855的博客 206

CKA-题库-简洁参考答案-反复练习20遍-必过!!!

新版CKA考试已于2020年9月1日正式上线! 考试模式:线上考试 考试时间:2小时 认证有效期:3年 软件版本:Kubernetes v1.19 重考政策:可接受1次重考 经验水平:中級 题目数量:17题 题库量小:随机的题目重复率极高 考试时可打开两个浏览器Tab,一个是考试窗口,一个用来查阅官方文档](https://kubernetes.io/docs/) 01 Task - 英文 Create a new ClusterRole named deployment-clusterrole tha.

随笔记录-分享&记忆 7315

java 最少使用(lru)置换算法_LRU和LFU缓存置换算法

为什么需要Cache为了解决俩个存储介质之间的速度不匹配,比如CPU和内存,比如内存和磁盘,比如本地和服务端。依据程序访问的局部性原理,近期访问的数据,在将来很有可能会被访问Cache是什么可以简单认为是一个HashMap,是一个key-value 结构,用来加速访问。Cache无处不在缓存的种类:本地服务器缓存、网页缓存、硬盘缓存、一级高速缓存、二级高速缓存等常用的Cache服务器Memcach...

weixin_39839726的博客 402

[Dify] 实现“多知识库切换”功能的最佳实践

知识库切换是提升AI问答系统精准度的关键技术。本文介绍了Dify平台实现多知识库切换的三种方式:静态配置、元数据过滤和动态切换,分析了各自的优缺点。最佳实践建议包括:合理分库设计、意图分类、主库优先检索等。文章还提供了示例工作流程和注意事项,帮助构建更智能、精准的知识驱动型问答系统。通过合理切换知识库,可显著提升回答相关性和系统性能。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 441

java 最少使用(lru)置换算法_缓存淘汰算法LRU和LFU

前言LRU算法和LFU算法是属于页面置换的一种算法,或者更通俗的说,就是缓存如何淘汰的一种策略。我们通常在设计一个系统的时候,由于数据库的读取速度远小于内存的读取速度,所以为了加快读取速度,会将一部分数据放到内存中,称为缓存。但是内存容量是有限的,当你要缓存的数据超出容量,就得有部分数据删除,这时候哪些数据删除,哪些数据保留,就是LRU算法和LFU算法要干的事。什么是LRU算法LRU算法,全称Le...

weixin_39721924的博客 457

Python数据分析师必备:OpenClaw开启Pandas清洗脚本自动生成新时代

本文介绍了OpenClaw这一AI智能体框架如何帮助Python数据分析师高效完成数据清洗工作。OpenClaw通过自然语言交互理解用户需求,自动生成Pandas清洗脚本,显著提升了数据清洗效率,降低了技术门槛。文章详细阐述了OpenClaw的工作原理、实战应用步骤及其在电商、金融、医疗等行业中的成功案例。相比传统手动编写脚本方式,OpenClaw能快速生成规范准确的清洗代码,使数据分析师能更专注于业务洞察。该工具为数据驱动决策提供了可靠支持,是数据分析领域的重要创新。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 228

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

fifo页面置换算法java_缓存算法(页面置换算法)-FIFO、LFU、LRU

转自:http://www.cnblogs.com/dolphin0520/1.FIFO算法FIFO(First in First out),先进先出。其实在操作系统的设计理念中很多地方都利用到了先进先出的思想,比如作业调度(先来先服务),为什么这个原则在很多地方都会用到呢?因为这个原则简单、且符合人们的惯性思维,具备公平性,并且实现起来简单,直接使用数据结构中的队列即可实现。在FIFO Cach...

weixin_34565946的博客 489

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

缓存置换算法之LRU/LFU

常见缓存置换算法 LRU 最近最久未使用 FIFO 先进先出置换算法 类似队列 OPT 最佳置换算法 (理想中存在的) NRU Clock置换算法 LFU 最少使用置换算法 PBA 页面缓冲算法 LRU 实现原理:链表+hash表 查询插入时间复杂度:O(1) 代码实现:LinkedHashMap dubbo的工具LRU工具类便是继承自LinkedHashMap:com.alibaba.dubbo.common.utils.LRUCache 数据结构 HashMap结构基础上,为所有Node节点维护一个

阿呆的专栏 514

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

关于FIFO,LRU,LFU的java代码实现

典型的例子是访问顺序为1,2,3,4,1,2,5,1,2,3,4,5时,分配3个物理页的缺页率(9次)比分配4个物理页(10次)更低。该算法维护一个队列,新调入的页面插入队尾,需要置换时从队头移除页面。思路非常的简单,就是用一个List列表存储其获取到的数值,并且每次缺页中断的时候去掉最前一个值,并且把新值插入到List尾部,如果没有产生缺页中断则不需要操作。这个和FIFO算法有相像之处,只不过是每次都要把对应的值从List中删除然后挪到最后,如果有缺页中断就把List的首去掉,并且在末尾加新值。

gyf3418840632的博客 423

操作系统页面置换算法Java实现(LFU,OPT,LRU,LFU,CLOCK)

操作系统页面置换算法Java实现(LFU,OPT,LRU,LFU,CLOCK)

ngczx的博客 1822

fifo算法_CPU中的高速缓存与置换算法

早期计算机仅限于固定用途的程序,程序是固定在电路板上的,修改程序的话,需要重新设计电路,冯诺依曼体系确立了通用的计算机结构。1.2 冯诺依曼体系概述输入设备:用于完成数据的接收,将数据送入到运算器中控制器:控制器是整个计算机的指挥控制中心,通过向其他设备发出控制信号来控制、控制计算机,使其能自动、协调地工作。运算器:在控制器的统一控制下,负责对数据进行加工、完成各种运算,如算术运算、逻辑运算、位移...

weixin_39764379的博客 493

分布式技术原理与实战45讲--41 第36讲:失效策略:缓存过期都有哪些策略?

这一课时的内容主要介绍了缓存的几种失效策略,并且分享了一个面试中的高频问题:LRU 缓存实现。缓存过期的策略来自操作系统,在我们的专栏中,对很多知识的展开都来自计算机原理、网络原理等底层技术,也从一个侧面反映了计算机基础知识的重要性。

g_z_q_的博客 268

中fifo算法_CPU中的高速缓存与置换算法

早期计算机仅限于固定用途的程序,程序是固定在电路板上的,修改程序的话,需要重新设计电路,冯诺依曼体系确立了通用的计算机结构。1.2 冯诺依曼体系概述输入设备:用于完成数据的接收,将数据送入到运算器中控制器:控制器是整个计算机的指挥控制中心,通过向其他设备发出控制信号来控制、控制计算机,使其能自动、协调地工作。运算器:在控制器的统一控制下,负责对数据进行加工、完成各种运算,如算术运算、逻辑运算、位移...

weixin_32616935的博客 553

缓存算法(FIFO 、LRU、LFU三种算法的区别)-没有实现删除尾部元素的功能

FIFO算法# FIFO 算法是一种比较容易实现的算法。它的思想是先进先出(FIFO,队列),这是最简单、最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小。空间满的时候,最先进入的数据会被最早置换(淘汰)掉。 FIFO 算法的描述:设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能: set(key,value):将记录(key,val...

trusause的博客 286

FIFO与LRU实现(Java)

一、概述 在学操作系统的时候,会接触到页面缓存调度算法。缓存不可能是无限大的,所以会涉及到一些置换策略,来保证缓存的命中率。常见的有:FIFO、LRU、LFU、OPT策略等。 1、缓存置换算法 FIFO:First In First Out,先进先出,和队列保持一致。最先进来的最早出去。 LRU:Least Recently Used,最近最少使用。总是淘汰最近没有...

weixin_30950607的博客 232

最近最少使用算法java_LeetCode之LRU Cache 最近最少使用算法 缓存设计

设计并实现最近最久未使用(Least Recently Used)缓存。题目描述:Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.get(key) - Get the value (wi...

weixin_36064484的博客 457
上一篇: Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
下一篇: 也许,这样理解HTTPS更容易
还不够
博客等级 码龄16年 113粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值