一、什么是LRU?

 LRU(Least Recently Used),最近最少使用。

是一种【内存管理】算法。

LRU算法基于一种假设:

长期不被使用的数据,在未来被用到的几率也不大。因此,当数据所占内存达到一定阈值时,移除掉最近最少使用数据。

LRU算法使用了一种有趣的数据结构,叫做【哈希链表

二、什么是【哈希链表】呢?

1)【哈希表】是由若干个【Key-Value】所组成的。

在“逻辑”上,这些Key-Value是无所谓排列顺序的,谁先谁后都一样。

2)  【哈希链表】当中,这些【Key-Value】不再是彼此无关的存在,而是被一个链条串起来了。

每一个Key-Value都具有它的前驱Key-Value、后继Key-Value,就像双向链表中的节点一样。

这样一来,原本无序的哈希表拥有了固定的排列顺序。

三、哈希链表和LRU算法有什么关系呢?

   1、依靠哈希链表的【有序性】,可以把Key-Value按照【最后的使用时间】来【排序】

让我们以用户信息的需求为例,来演示一下LRU算法的基本思路:

1.假设我们使用哈希链表来缓存用户信息,目前缓存了4个用户,这4个用户是按照时间顺序依次从链表右端插入的。

2.此时,业务方访问用户5,由于哈希链表中没有用户5的数据,我们从数据库中读取出来,插入到缓存当中。

这时候,链表中最右端是最新访问到的用户5,最左端是最近最少访问的用户1。

3.接下来,业务方访问用户2,哈希链表中存在用户2的数据,我们怎么做呢?

我们把用户2从它的前驱节点和后继节点之间移除,重新插入到链表最右端。

这时候,链表中最右端变成了最新访问到的用户2,最左端仍然是最近最少访问的用户1。

4. 接下来,业务方请求修改用户4的信息。

同样道理,我们把用户4从原来的位置移动到链表最右侧,并把用户信息的值更新。

这时候,链表中最右端是最新访问到的用户4,最左端仍然是最近最少访问的用户1。

5  后来业务方换口味了,访问用户6,用户6在缓存里没有,需要插入到哈希链表。

假设这时候缓存容量已经达到上限,必须先删除最近最少访问的数据,那么位于哈希链表最左端的用户1就会被删除掉,然后再把用户6插入到                      最右端。

以上,就是LRU算法的基本思路。

Java中的LinkedHashMap已经对【哈希链表】做了很好的实现。private Node head;private Node end;//缓存存储上限private int limit;private HashMap<String, Node> hashMap;public LRUCache(int limit) {this.limit = limit;hashMap = new HashMap<String, Node>();}public String get(String key) {Node node = hashMap.get(key);if (node == null){return null;}refreshNode(node);return node.value;}public void put(String key, String value) {Node node = hashMap.get(key);if (node == null) {//如果key不存在,插入key-valueif (hashMap.size() >= limit) {String oldKey = removeNode(head);hashMap.remove(oldKey);}node = new Node(key, value);addNode(node);hashMap.put(key, node);}else {//如果key存在,刷新key-valuenode.value = value;refreshNode(node);}}public void remove(String key) {Node node = hashMap.get(key);removeNode(node);hashMap.remove(key);}/*** 刷新被访问的节点位置* @param  node 被访问的节点*/private void refreshNode(Node node) {//如果访问的是尾节点,无需移动节点if (node == end) {return;}//移除节点removeNode(node);//重新插入节点addNode(node);}/*** 删除节点* @param  node 要删除的节点*/private String removeNode(Node node) {if (node == end) {//移除尾节点end = end.pre;}else if(node == head){//移除头节点head = head.next;} else {//移除中间节点node.pre.next = node.next;node.next.pre = node.pre;}return node.key;}/*** 尾部插入节点* @param  node 要插入的节点*/private void addNode(Node node) {if(end != null) {end.next = node;node.pre = end;node.next = null;}end = node;if(head == null){head = node;}}class Node {Node(String key, String value){this.key = key;this.value = value;}public Node pre;public Node next;public String key;public String value;}public static void main(String[] args) {LRUCache lruCache = new LRUCache(5);lruCache.put("001", "用户1信息");lruCache.put("002", "用户1信息");lruCache.put("003", "用户1信息");lruCache.put("004", "用户1信息");lruCache.put("005", "用户1信息");lruCache.get("002");lruCache.put("004", "用户2信息更新");lruCache.put("006", "用户6信息");System.out.println(lruCache.get("001"));System.out.println(lruCache.get("006"));}需要注意的是,这段不是线程安全的,要想做到线程安全,需要加上synchronized修饰符。对于用户系统的需求,也可以使用【缓存数据库Redis】实现,Redis底层也实现了类似于LRU的回收算法。

LRU(最近最少使用)算法相关推荐

  1. 最近最少使用算法(LRU)

    最近最少使用算法(LRU) LRU 英文全称 "Least Recently Used",即最近最少使用,属于典型的内存管理算法. LRU用通俗的话来说就是最近被频繁访问的数据会具 ...

  2. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  3. 算法必知 --- LRU缓存淘汰算法

    作者:_code_x 链接:https://www.jianshu.com/p/b7fed77324b9 写在前 就是一种缓存淘汰策略. 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾 ...

  4. Java--缓存热点数据,最近最少使用算法

    1.最近最少使用算法LRU (Least recently used,最近最少使用) [实现]:最常见的是使用一个链表保存缓存数据 1.新数据插入到链表头部: 2.每当缓存命中(即缓存数据被访问),将 ...

  5. 06 | 链表(上):如何实现LRU缓存淘汰算法?

    缓存 作用 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存.数据库缓存.浏览器缓存等等. 淘汰策略 常见的策略有三种:先进先出策略 FIFO(F ...

  6. 页面置换算法——最佳置换算法、最近最少使用算法、先进先出算法、时钟置换算法

    计算机操作系统--页面置换算法 根据中国大学MOOC计算机操作系统(电子科技大学)而写. 如果自己要设计页面置换,要根据什么原则来设计?我们首先想到的是存储器的局部性原理(时间局部性.空间局部性) P ...

  7. leetcode刷题:LRU缓存淘汰算法

    题目: 分析: 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置.但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用.那么, ...

  8. 看动画轻松理解「链表」实现「 LRU 缓存淘汰算法」

    作者 | 吴至波 责编 | 胡巍巍 快速挑战Python全栈工程师: https://edu.csdn.net/topic/python115?utm_source=csdn_bw 前几节学习了「链表 ...

  9. 操作系统之页面置换算法(FIFO、LFU、LRU、OPT算法)

    操作系统之页面置换算法(FIFO.LFU.LRU.OPT算法) TIPS: 主存:实际上的物理内存. 虚存(虚拟内存):虚拟存储技术.虚拟内存使计算机系统内存管理的一种技术.它使得应用程序认为它拥有的 ...

  10. 看动画理解「链表」实现LRU缓存淘汰算法

    前几节学习了「链表」.「时间与空间复杂度」的概念,本节将结合「循环链表」.「双向链表」与 「用空间换时间的设计思想」来设计一个很有意思的缓存淘汰策略:LRU缓存淘汰算法. 循环链表的概念 如上图所示: ...

最新文章

  1. 未处理的异常: 0xC0000235: 由句柄所调用的 NtClose 已使用 NtSetInformationObject 以防止关闭。...
  2. 6a标准 api_【阀门标准】API SPEC 6A CHINESE-2010中文版.pdf
  3. html2canvas的踩坑之路
  4. Sql Server 2005如何设置连接加密
  5. 小目标神器!TPH-YOLOv5:将Transformer预测加载Yolov5!
  6. 解读全球热点,传递科研进展,这份AI内参要承包你的AI信息源
  7. 贺利坚老师汇编课程23笔记:用DEBUG跟踪程序的执行
  8. [转]反射(用反射调用任意.net库中的方法)
  9. 7.2.5 dps 测试软件,dps排行榜网站_7.1.5dps排行榜分享DPS模拟常见上榜翻译2
  10. kali linux暴力破解wifi密码
  11. 专访AWR市场副总裁Sherry Hess:全面发力 深耕中国市场
  12. 【DeepLearning】【环境配置】Ubuntu 下手动调节 Nvidia 显卡风扇转速
  13. 超人视觉怎么样/机器视觉培训适合报培训班吗
  14. k8s-某视频课命令问题排查了解
  15. 电脑计算器所有快捷键
  16. 假如有人把支付宝的服务器炸了, 存在支付宝里的钱是不是没了?
  17. Codeforces Round #786 (Div. 3) Editorial(A/B/C/D)待补
  18. three.js光效扫描
  19. Mall的docker发布实例
  20. SoundPool类简介与适用场合

热门文章

  1. APP软件项目的费用
  2. (bok) 利用泰勒级数sin(x)=x-x^3/3!+x^5/5!-x^7/7!+x^9/9!-... 计算sin(x)的值。要求最后一项的绝对值小于10^(-5), 并统计出此时累计了多少项?
  3. AutoCAD Civil 3D获取任意桩号处的超高值
  4. 代码随想录算法训练营第08天 | LeetCode 344.反转字符串,541. 反转字符串2,剑指Offer 05.替换空格,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串
  5. Linux ftrace 1.5、syscall event
  6. 注意力专注软件推荐——番茄ToDo
  7. 【一朵花儿——效果+代码 Html+JavaScript+CSS】
  8. 史上最牛C语言控制台游戏!C语言控制台音游——Rhythm Slasher! 附上源代码供交流学习
  9. (转)什么妨碍我们进步
  10. Caused by: *.InvalidFormatException: Cannot deserialize value of type....