LRU原来如此简单

article/2025/9/29 19:03:42

文章目录

  • 前言
  • 一、LRU是什么?
  • 二、LFU是什么?
  • 三、LRU和LFU的比较
  • 四、LFU代码实现(看懂LFU就自然懂了LRU了)
    • 1、LFU类
    • 2、Node类
    • 3、测试
  • 写在最后,感谢点赞关注收藏转发


前言

现在缓存技术在项目中随处可见,但是有一点,毕竟缓存这个东西还是稀有的,毕竟不像硬盘资源那么广,所以缓存如何高效的使用,不浪费,及时保存热点数据那可是很重要的了。接下来带你了解下大名鼎鼎的LRU以及LFU,以及用代码是如何实现的

一、LRU是什么?

LRU全称 “Least Recently Used”,最近最少使用策略,判断最近被使用的时间,距离目前最远的数据优先被淘汰,作为一种根据访问时间来更改链表顺序从而实现缓存淘汰的算法。
简单介绍:就是经常使用的数据在链表的头部,冷数据在尾部,一旦链表容量不够(缓存空间满了),执行删除尾部策略。一般来说链表的增删是快,但是有个缺点就是查询慢,LRU为了获取元素快,肯定是不能每次逐个遍历获取的元素的,所以还有个HashMap来获取你需要的元素,复杂度O(1)。

二、LFU是什么?

LFU,全称是:Least Frequently Used,最不经常使用策略,在一段时间内,数据被使用频次最少的,优先被淘汰。最少使用(LFU)是一种用于管理计算机内存的缓存算法。主要是记录和追踪内存块的使用次数,当缓存已满并且需要更多空间时,系统将以最低内存块使用频率清除内存.采用LFU算法的最简单方法是为每个加载到缓存的块分配一个计数器。每次引用该块时,计数器将增加一。当缓存达到容量并有一个新的内存块等待插入时,系统将搜索计数器最低的块并将其从缓存中删除。redis启用回收策略就有LFU

三、LRU和LFU的比较

其实LFU比LRU多了一个就是每次添加,获取增加次数记录。在链表的开始插入元素,然后每插入一次计数一次,接着按照次数重新排序链表,如果次数相同的话,按照插入时间排序,然后从链表尾部选择淘汰的数据。

LRU和LFU侧重点不同,LRU主要体现在对元素的使用时间上,而LFU主要体现在对元素的使用频次上。LFU的缺陷是:在短期的时间内,对某些缓存的访问频次很高,这些缓存会立刻晋升为热点数据,而保证不会淘汰,这样会驻留在系统内存里面。而实际上,这部分数据只是短暂的高频率访问,之后将会长期不访问,瞬时的高频访问将会造成这部分数据的引用频率加快,而一些新加入的缓存很容易被快速删除,因为它们的引用频率很低。

四、LFU代码实现(看懂LFU就自然懂了LRU了)

1、LFU类

在这里插入代码片public class LFU<K, V> {/*** 容量*/private int capacity;private Map<K, Node> caches;/*** 添加** @param key* @param value*/public void put(K key, V value) {Node node = caches.get(key);if (node == null) {if (capacity == caches.size()) {//去除不活跃的数据K leastKey = removeLeastCount();caches.remove(leastKey);}node = new Node(key, value, System.nanoTime(), 1);caches.put(key, node);} else {node.value = value;node.setCount(node.getCount() + 1);node.setTime(System.nanoTime());}sort();}/*** 获取元素** @param key* @return*/public V get(K key) {Node node = caches.get(key);if (node != null) {node.setCount(node.getCount() + 1);node.setTime(System.nanoTime());sort();return (V) node.value;}return null;}/*** 排序*/private void sort() {List<Map.Entry<K, Node>> list = new ArrayList<>(caches.entrySet());Collections.sort(list, new Comparator<Map.Entry<K, Node>>() {@Overridepublic int compare(Map.Entry<K, Node> o1, Map.Entry<K, Node> o2) {//调用 Node重写的compable方法return o2.getValue().compareTo(o1.getValue());}});caches.clear();for (Map.Entry<K, Node> kNodeEntry : list) {caches.put(kNodeEntry.getKey(), kNodeEntry.getValue());}}/*** 移除统计数或者时间比较最小的那个** @return*/private K removeLeastCount() {Collection<Node> values = caches.values();//min 方法会调用 Node重写的compable方法Node min = Collections.min(values);return (K) min.getKey();}public LFU() {}public LFU(int size) {this.capacity = size;caches = new LinkedHashMap<>(size);}public int getCapacity() {return capacity;}public void setCapacity(int capacity) {this.capacity = capacity;}public Map<K, Node> getCaches() {return caches;}public void setCaches(Map<K, Node> caches) {this.caches = caches;}
}

2、Node类

package com.cloud.order.util;public class Node implements Comparable<Node> {Object key;Object value;long time;int count;@Overridepublic int compareTo(Node o) {//在数目相同的情况下 比较时间int compare = Integer.compare(this.count, o.count);if (compare == 0) {return Long.compare(this.time, o.time);}return compare;}public Node() {}public Node(Object key, Object value, long time, int count) {this.key = key;this.value = value;this.time = time;this.count = count;}public Object getKey() {return key;}public void setKey(Object key) {this.key = key;}public Object getValue() {return value;}public void setValue(Object value) {this.value = value;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}
}

3、测试

package com.cloud.order.util;import java.util.Map;public class TestLru {public static void main(String[] args) {LFU<Integer, String> lfuList = new LFU<>(5);lfuList.put(1, "A");lfuList.put(2, "B");lfuList.put(3, "C");lfuList.put(4, "D");lfuList.put(5, "E");lfuList.put(6, "F");Map<Integer, Node> caches = (Map<Integer, Node>) lfuList.getCaches();for (Map.Entry<Integer, Node> nodeEntry : caches.entrySet()) {System.out.println(nodeEntry.getValue().value);}}
}

写在最后,感谢点赞关注收藏转发

欢迎关注我的微信公众号 【猿之村】
在这里插入图片描述

来聊聊Java面试
加我的微信进一步交流和学习,微信手动搜索
【codeyuanzhicunup】添加即可
如有相关技术问题欢迎留言探讨,公众号主要用于技术分享,包括常见面试题剖析、以及源码解读、微服务框架、技术热点等。


http://chatgpt.dhexx.cn/article/hJyPXtCt.shtml

相关文章

LRU算法详解

概念理解 1.LRU是Least Recently Used的缩写&#xff0c;即最近最少使用页面置换算法&#xff0c;是为虚拟页式存储管理服务的&#xff0c;是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况&#xff0c;只能利用“最近的过去”作为“最近的将来”的…

LRU算法

1.什么是LRU算法 LRU算法又称最近最少使用算法&#xff0c;它的基本思想是长期不被使用的数据&#xff0c;在未来被用到的几率也不大&#xff0c;所以当新的数据进来时我们可以优先把这些数据替换掉。 在LRU算法中&#xff0c;使用了一种有趣的数据结构&#xff0c;称为哈希链…

巧用 NGINX 实现大规模分布式集群的高可用性

原文作者&#xff1a;陶辉 原文链接&#xff1a;巧用 NGINX 实现大规模分布式集群的高可用性 - NGINX开源社区 转载来源&#xff1a;NGINX开源社区 本文是我对2019年GOPS深圳站演讲的文字整理。这里我希望带给各位读者的是&#xff0c;如何站在整个互联网背景下系统化地理解Ngi…

朱邦复

朱邦复 求助编辑百科名片 朱邦复&#xff0c;仓颉输入法的发明人&#xff0c;现任香港上市公司文化传信集团的副主席。湖北省黄冈县人。为中文终端机、仓颉输入法、汉卡的发明人。由于其对中文电脑发展的众多贡献&#xff0c;台湾及香港地区的华人誉其为“中文电脑之父”、“中…

TCP/IP的底层队列实现原理

个人博客请访问 http://www.x0100.top 自从上次学习了TCP/IP的拥塞控制算法后&#xff0c;我越发想要更加深入的了解TCP/IP的一些底层原理&#xff0c;搜索了很多网络上的资料&#xff0c;看到了陶辉大神关于高性能网络编程的专栏&#xff0c;收益颇多。今天就总结一下&#…

从码农到工程师:看一下这6点!

作者&#xff1a;陶辉笔记来源&#xff1a;http://www.taohui.pub 许多程序员自称码农&#xff0c;因为每天事情总也做不完&#xff0c;而这些工作也没有给自己带来职业上的提升&#xff0c;总在原地打转&#xff0c;自己的工作似乎随时可被新人替换&#xff0c;可有可无。于是…

Nginx五大类变量详解

Nginx变量详解 文章目录 Nginx变量详解一、HTTP请求相关的变量二、TCP连接相关的变量三、Nginx处理请求过程中产生的变量四、发送HTTP响应时相关的变量五、Nginx系统变量 为了方便记忆呢&#xff0c;我把nginx的全部变量分为5种&#xff0c;详情见下图 本文内容取自极客时间陶辉…

开复博士见面会

CSDN的CTO俱乐部成立一年多来&#xff0c;做过很多次活动了。我只参加了两次&#xff0c;第二次就是开复博士的创新工厂介绍会。我对创新工厂兴趣并不大&#xff0c;但很想近距离接触一下这位声名远播的演讲者和布道者。 曾经和一个&#xff36;&#xff30;的会议上&#xff…

Nginx核心知识100讲学习笔记(陶辉)Nginx架构基础(一)

(转载&#xff0c;非常不错的文章) 一、Nginx的请求处理流程进程结构 1、Nginx的请求处理流程 2、Nginx的进程结构 3、进程作用 1、Master进程 1、是进行work进程的监控管理的2、看看work进程是否正常工作需不需要进行热部署、需不需要重新载入配置文件 2、Cache manager …

在这里,NGINX 创始人 Igor Sysoev 将亲述 NGINX 的诞生史

2020 年 5 月 20 日&#xff0c;一场 NGINX 在国内的盛会、一个所有 NGINX 用户 & 爱好者朝圣的最佳场所&#xff0c;F5 线上技术峰会 – NGINX 专场将以线上直播的形式面向所有开发者召开。届时各位 NGINX 开发者心目中的偶像 NGINX 创始人 Igor Sysoev 以及国内 NGINX 技…

如何用NGINX实现UDP四层反向代理?

原文作者&#xff1a;陶辉 原文链接&#xff1a;如何用NGINX实现UDP四层反向代理&#xff1f;- NGINX开源社区 转载来源&#xff1a;NGINX开源社区 在实时性要求较高的特殊场景下&#xff0c;简单的UDP协议仍然是我们的主要手段。 UDP协议没有重传机制&#xff0c;还适用于同时…

Nginx深度剖析,真是被大牛讲透了

开篇 Nginx是一款非常出色的服务器软件&#xff0c;从开始工作到现在&#xff0c;周围所有的公司都在使用Nginx。在多年的使用过程中&#xff0c;逐渐对Nginx的源码产生了浓厚的兴趣&#xff0c;我不满足于仅仅会使用&#xff0c;我想更加深入的理解它的内部工作原理。只有深入…

CPGIS三十周年专访系列|陶闯主席

近日&#xff0c;国际华人地理信息科学协会CPGIS建会30周年之际&#xff0c;开展了一次历届主席专访活动&#xff0c;陶闯博士作为国际华人地理信息科学协会CPGIS&#xff0c;2000-2001届的主席&#xff0c;接受了CPGIS的专访&#xff0c;忆往昔&#xff0c;看今朝&#xff0c;…

【10道大厂必考的计算机网络问题】陶辉老师

目录 1.请详细介绍一下TCP的三次握手协议,为什么要三次握手&#xff1f; 2.说说HTTP协议中缓存的处理流程&#xff1f;缓存的应用流程&#xff1f;与缓存相关的HTTP头部&#xff1f; 3.在地址栏键入URL后,网络世界发生了什么&#xff1f; 4.使用HTTP长连接有哪些优点&#…

HTTP详细介绍

转自&#xff1a;HTTP详细介绍本文参考 wiki百科、陶辉老师《Web协议详解与抓包实战》 和 作者在一线多年的运维工作总结希望对大家有所帮助。常见osi模型(7层)发起组织&#xff1a; 国际电信联盟电信标准化部门&#xff0c;与国际标准组织&#xff08;ISOhttps://www.pinlue.c…

10 道大厂面试必考的计算机网络问题-陶辉 极客时间

大厂中更多会考察你的长板. 在大厂中要学会求助 1.TCP的三次握手机制,为什么要三次? 为什么需要握手? 需要同步序列号,当然也有MSS(最大报文段长度),滑动窗口. 为什么是3次? 正常想法应该是: C:我要建连接,我的seq是这个; S:我收到了 S:我的Seq是这个 C:我也收到了…

TVP思享 | 四个全新维度,极限优化HTTP性能

导语 | 当产品的用户量不断翻番时&#xff0c;需求会倒逼着你优化HTTP协议。那么&#xff0c;要想极限优化HTTP性能&#xff0c;应该从哪些维度出发呢&#xff1f;本文将由TVP陶辉老师&#xff0c;为大家分享四个全新维度。「TVP思享」专栏&#xff0c;凝结大咖思考&#xff0c…

uni-app从入门到放弃(一)

文章目录 一、uni-app简单介绍什么是uni-app&#xff1f;uni-app的优点跨平台发行&#xff0c;运行体验更好通用前端技术栈,学习成本更低开发生态,组件更丰富 二、功能框架浏览图三、创建项目1、安装HBuilderX2、创建uni-app3、运行项目4、官方提示 四、项目中使用扩展组件五、…

CUDA——从入门到放弃

1. 知识准备 1.1 中央处理器&#xff08;CPU&#xff09; 中央处理器&#xff08;CPU&#xff0c;Central Processing Unit&#xff09;是一块超大规模的集成电路&#xff0c;是一台计算机的运算核心&#xff08;Core&#xff09;和控制核心&#xff08; Control Unit&#xf…

MySQL从入门到放弃(三)

插入数据 插入数据之前首先创建一张persons表 CREATE TABLE persons( id INT NOT NULL AUTO_INCREMENT, name CHAR(40) NOT NULL DEFAULT 无名, age INT NOT NULL DEFAULT 0, info CHAR(50) NULL, PRIMARY KEY(id) ); 为表的所有字段插入数据 一次插入一条数据 INSERT INTO…