如何通俗易懂的理解LRU算法?

1.LRU是什么?

LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统。

LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大。因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据。

LRU算法应用:可以在内存不够时,从哈希表移除一部分很少访问的用户。

LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常著名的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,会存在一种缓存淘汰机制,每次从内存中找到最久未使用的数据然后置换出来,从而存入新的数据!它的主要衡量指标是使用的时间,附加指标是使用的次数。在计算机中大量使用了这个机制,它的合理性在于优先筛选热点数据,所谓热点数据,就是最近最多使用的数据!因为,利用LRU我们可以解决很多实际开发中的问题,并且很符合业务场景。

2.LRU的需求

首先考虑这样的一个业务场景,小王在A公司上班,有一天产品提出了一个需求:“咱们系统的用户啊,每天活跃的就那么多,有太多的僵尸用户,根本不登录,你能不能考虑做一个筛选机制把这些用户刨出去,并且给活跃的用户做一个排名,我们可以设计出一些奖励活动,提升咱们的用户粘性,咱们只需要关注那些活跃的用户就行了“”。小王连忙点头,说可以啊,然而心里犯起嘀咕来了:这简单,按照常规思路,给用户添加一个最近活跃时间长度和登录次数,然后按照这两个数据计算他们的活跃度,最后直接排序就行了。嘿嘿,简直完美!不过!用户表字段已经很多了,又要加两个字段,然后还得遍历所有的数据排序?这样查询效率是不是会受影响啊?

3.LRU的实现方式

实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存;
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

3.1 直接继承LinkedHashMap来实现

public class Code_LRU {class LRUCache extends LinkedHashMap<Integer,Integer>{private int capacity;public LRUCache(int capacity) {super(capacity,0.75F,true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key,-1);}public void put(int key,int value) {super.put(key, value);}// 重写淘汰策略protected boolean removeEldestEntry(Map.Entry<Integer, Integer> edlest) {return size()>capacity;}}
}

3.2 用双向链表+hashMap来实现

// 解题思路:双向链表+hashmap来实现class LRUCache_2{// 双向链表class DLinkedNode{int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int key,int value) {this.key = key;this.value = value;}}// hashmapprivate HashMap<Integer,DLinkedNode> cache = new HashMap<>();// 定义私有变量private int size;private int capacity;private DLinkedNode head,tail;public LRUCache_2(int capacity) {this.size = 0;this.capacity = capacity;// 生成伪头部和伪尾部结点head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}//获得值public int get(int key) {DLinkedNode node = cache.get(key);if(node==null) {return -1;}else {// 如果key存在,哈希表定位 结点移动到头部moveToHead(node);return node.value;}}// 放入值的操作public void put(int key,int value) {DLinkedNode node = cache.get(key);// 如果key不存在if(node==null) {// 新创建一个结点DLinkedNode newNode = new DLinkedNode(key,value);// 添加cache.put(key,newNode);// 添加到头部addToHead(newNode);++size;// 判断容量if(size>capacity) {// 称号出容量DLinkedNode tail = removeTail();// 删除hash表中对应的项cache.remove(tail.key);--size;}}else {node.value = value;// 移动moveToHead(node);}}// 添加结点的操作private void addToHead(DLinkedNode node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}// 删除结点private void removeNode(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;}// 移动到头结点 删结点 填充结点private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}// 删除尾部结点private DLinkedNode removeTail() {DLinkedNode res = tail.prev;removeNode(res);return res;}}

【大话Java面试】-如何通俗易懂的理解Redis的回收算法LRU?相关推荐

  1. 【11-JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS、G1和ZGC垃圾回收器你有过了解吗?】

    JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS.G1和ZGC垃圾回收器你有过了解吗? JVM面试专题-说说你知道的垃圾回收算法?垃圾回收器你知道吗?CMS.G1和ZGC垃圾回收器 ...

  2. BAT研发Java面试36题总结:Spring+Redis+Docker+Dubbo

    一面: ArrayList和linkedlist区别.ArrayList是否会越界. ArrayList和hashset有何区别.hashset存的数是有序的么. volatile和synchroni ...

  3. Java面试官最爱问的垃圾回收机制,Java编程配置思路详解

    Java编程配置优点:相对于xml配置而言,其结构更清晰,可读性更高,同时也节省了解析xml耗时. Java编程配置缺点:修改应用配置参数需要重新编译.其实并不是一个大的问题,实际生成环境中,应用配置 ...

  4. Java面试官最爱问的垃圾回收机制,这位阿里P7大佬分析总结的属实到位

    可达性分析算法:判断对象的引用链是否可达 可达性分析算法是通过判断对象的引用链是否可达来决定对象是否可以被回收. 可达性分析算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,通过一系列的 ...

  5. java面试突击-2022最新迭代redis\mq\springCloud-纯手打

    本博客是本人纯手打然后去网上百度的图片,转发请注明出处 按照自己的理解适合给初级程序员找工作用的 顺便给自己回顾一下,都是按照自己的理解来写的,有的地方不通顺或者不理解可以问我,有写不对的地方或者不同 ...

  6. 自制java面试宝典-从深层次理解

    面向对象的理解 面向对象–>面向过程 完成同一件事需要拆分成多个步骤,对于面向过程,每个函数就是一个步骤,而对于面向对象,他将多个步骤封装在一个对象里面,然后多个对象协同完成这件事. 面向对象的 ...

  7. 上海大厂Java面试经历:初步理解类加载运行机制和类加载过程

    volatile相关经典面试题 谈谈volatile的特性 volatile的内存语义 说说并发编程的3大特性 什么是内存可见性,什么是指令重排序? volatile是如何解决java并发中可见性的问 ...

  8. 【Java面试宝典】深入理解JAVA虚拟机

    一.运行时数据区域 线程隔离:线程隔离的意思,就是给不同的线程多分配的资源用,以做到不争用. 线程共享:线程共享就是资源只有一个没有办法分配更多,只能共享. Java虚拟机管理的内存包括几个运行时数据 ...

  9. Java面试官最爱问的垃圾回收机制,mysqlssl连接

    说在前面 已经到了月中旬了,程序员们即将迎来面试季,今天刚好有一位粉丝找到我,他上周刚面完奇虎360,经过了几轮的面试,最后薪资也谈了,今天主要是问我想这样的大型互联网公司一般多久会正式下offer. ...

最新文章

  1. jvm:运行时数据区
  2. koa cookie使用
  3. 软件架构师的工作流程
  4. 将2个字符写入单个Java char
  5. ie浏览器网页版进入_IE浏览器打开网页提示无法打开Internet站点的解决办法
  6. IFrame标签的两个用法介绍
  7. Openstack(二)基本环境准备--网络、时间、yum源等
  8. Python 3.7 即将发布,引入多项新功能!
  9. python学习网站-Python学习网站
  10. 深度学习14-实战三-Google涂鸦识别挑战项目(上)
  11. libgsm.a relocation R_X86_64_PC32 can not be used when making a shared object; recompile with -fPIC
  12. 蓝牙鼠标windows linux,在Deepin和Windows 10双系统中蓝牙4.0鼠标共享使用的方法
  13. python使用scrapy爬取百度地图POI数据
  14. SPC统计及控制图系列标准
  15. 服务器版dll修复工具,DLL修复工具哪个好?五款修复能力强推荐
  16. 全新小说安装教程小程序源码
  17. elasticsearch系列二:索引详解(快速入门、索引管理、映射详解、索引别名)
  18. K210入门,用wifi通讯
  19. Python趣用—配平化学方程式
  20. MySQL的文本导入之load data local

热门文章

  1. jmeter巧用ForEach控制器
  2. 护肤-洗护用品-的那些事
  3. 零点起飞学java视频_零点起飞学java (刘升华) 高清PDF_IT教程网
  4. Java随笔——逻辑运算符和(|和||)之间的区别
  5. matlab中给信号添加高斯白噪声的两种方法,awgn计算过程,randn函数
  6. C语言关于指针知识点总结【2】
  7. selenium无登录状态爬取Boss直聘
  8. 《吐血整理》Linux面试题Top100@面试官你好,我精通Linux!嘿嘿~
  9. 工程技术x计算机科学,TOP期刊Transactions on Industrial Electronics(TIE),投稿流程介绍
  10. vue移动端使用手势库---alloytinger