一、算法介绍

最近最久未使用(Least Recently Used    LRU)算法是⼀种缓存淘汰策略,它是大部分操作系统为最大化页面命中率而广泛采用的一种页面置换算法。该算法的思路是,发生缺页中断时,将最近一段时间内最久未使用的页面置换出去。 从程序运行的原理来看,最近最久未使用算法是比较接近理想的一种页面置换算法,这种算法既充分利用了内存中页面调用的历史信息,又正确反映了程序的局部问题

虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,其余页面放入外存的管理方式。
有利就有弊,虚拟页式存储管理减少了进程所需的内存空间,却也带来了运行时间变长这一缺点:进程运行过程中,不可避免地要把在外存中存放的一些信息和内存中已有的进行交换,由于外存的低速,这一步骤所花费的时间不可忽略。因而,采取尽量好的交换算法以减少读取外存的次数,也是相当有意义的事情。

二、基本原理

假设 序列为 4 3 4 2 3 1 4 2
物理块有3个
4调入内存 4
3调入内存 3 4
4调入内存 4 3
2调入内存 2 4 3
3调入内存 3 2 4
1调入内存 1 3 2(因为最少使用的是4,所以丢弃4)
4调入内存 4 1 3(原理同上)
2调入内存 2 4 1

规律就是,如果新存入或者访问一个值,则将这个值放在队列开头。如果存储容量超过上限cap,那么删除队尾元素,再存入新的值。

我们下面通过一个简单的存储int的方式来实现LRU cache,实现put和get功能。

三、数据结构

⾸先要接收⼀个参数作为缓存的最⼤容量, 然后实现两个 API, ⼀个是 put(key, val) ⽅法存⼊键值对,get(key) ⽅法获取 key 对应的 val, 如果 key 不存在则返回null,get 和 put ⽅法必须都是 O(1) 的时间复杂度。

因此LRU cache 的数据结构的必要的条件: 查找快, 插⼊快, 删除快, 有顺序之分。那么, 什么数据结构同时符合上述条件呢? 哈希表查找快, 但是数据⽆固定顺序; 链表有顺序之分, 插⼊删除快, 但是查找慢。 所以结合⼀下, 形成⼀种新的数据结构: 哈希链表。如下图所示:

四、算法细节

新插入的元素或者最新查询的元素要放到链表的头部,对于长时间未访问的元素要放到链表尾部,所以每次插入或者查询都需要维护链表中元素的顺序。

使用哈希表的原因是查询时间复杂度为O(1),使用双向链表的原因是对于删除和插入操作时间复杂度为O(1)。

其中哈希表中存储的 key 为 K,value 为 Node<K,V> 的引用,双向链表存储的元素为Node<K,V>的引用.

put 方法是线程安全方法,定义如下所示:

public synchronized void put(K key,V value)

对于put操作:

①首先判断缓存中 元素 K 是否存在,如果存在,则把链表中的元素Node<K, V>删除,map中的数据<K, Node<K, V> >不用删除,再在链表头部插入元素,并更新map,直接返回即可 ;

②缓存不存在,并且缓存没有满的话,直接把元素插入链表的表头,缓存满了的话移除表尾元素(最旧未访问元素),将元素K插入表头,增加map中的<K, Node<K, V>>, 更新map。

get 方法是线程安全方法,定义如下所示:

public synchronized V get(K key)

对于get操作:

首先要判断 缓存中(map)是否存在,如果存在则把该节点删除并在链表头部插入该元素并更新map 返回当前元素即可,如果map不存在 则直接返回null;

五、算法实现

public class LRUCache {class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int _key, int _value) {key = _key; value = _value;}}private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(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;}// 如果 key 存在,先通过哈希表定位,再移到头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node = cache.get(key);if (node == null) {// 如果 key 不存在,创建一个新的节点DLinkedNode newNode = new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode tail = removeTail();// 删除哈希表中对应的项cache.remove(tail.key);--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部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;}
}

六、总结

LRU算法(JAVA实现)相关推荐

  1. LRU算法java实现

    LRU全称是Least Recently Used,即最近最久未使用的意思. LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已 ...

  2. 缓存淘汰策略—LRU算法(java代码实现)

    LRU 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高" ...

  3. LRU算法 Java

    LRU算法/LRU(Least recently used) 算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也更高. 请你设计并实现一个满 ...

  4. 缓存淘汰算法--LRU算法

    缓存淘汰算法--LRU算法 参考: https://www.cnblogs.com/dailidong/p/7571178.html https://blog.csdn.net/wangxilong1 ...

  5. java 最少使用(lru)置换算法_「面试」LRU了解么?看看LinkedHashMap如何实现LRU算法...

    以下内容均是本人原创,希望你看完之后能有更多更深入的了解,欢迎关注➕ 问题:使用Java完成一个简单的LRU算法 什么是LRU算法 LRU(Least Recently Used),也就是最近最少使用 ...

  6. 使用java.util.LinkedList模拟实现内存页面置换算法--LRU算法

    一,LRU算法介绍 LRU是内存分配中"离散分配方式"之分页存储管理方式中用到的一个算法.每个进程都有自己的页表,进程只将自己的一部分页面加载到内存的物理块中,当进程在运行过程中, ...

  7. java 最少使用(lru)置换算法_缓存置换算法 - LRU算法

    LRU算法 1 原理 对于在内存中并且不被使用的数据块就是LRU,这类数据需要从内存中删除,以腾出空间来存储常用的数据. LRU算法(Least Recently Used,最近最少使用),是内存管理 ...

  8. LRU算法及Java实现

    LRU算法介绍 LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法,为虚拟页式存储管理服务.LRU算法的提出,是基于这样一个事实:在前面几条指令中使用频繁的页面很 ...

  9. java 最少使用(lru)置换算法_「Redis源码分析」Redis中的LRU算法实现

    如果对我的文章感兴趣.希望阅读完可以得到你的一个[三连],这将是对我最大的鼓励和支持. LRU是什么 LRU(least recently used)是一种缓存置换算法.即在缓存有限的情况下,如果有新 ...

  10. java lru笔试题,2016年头条校招笔试(LRU算法)

    题目 操作系统中可以使用 LRU(Least Recently Used)内存淘汰旧数据的策略,如果内存需要加载新数据但空间不足,则会按照最近访问时间进行排序,并将最老的数据淘汰.假设现在内存空间大小 ...

最新文章

  1. windows7下vs2008常见错误解决方法汇总
  2. JS编程建议——7:小心保留字的误用
  3. java开发后台技术_java开发后台的技术
  4. HAN:基于双层注意力机制的异质图深度神经网络
  5. jetty java 禁用目录列表_java – 如何禁用Jetty的WebAppContext目录列表?
  6. Ajax链接输出数据库
  7. Python笔记-flask执行后台程序(非web应用)
  8. 在多线程数据平面开发套件(DPDK)应用程序中优化内存使用
  9. python机器学习库sklearn——交叉验证(K折、留一、留p、随机)
  10. android转usb工具,绿联Type-C转Micro usb数据线,Type-C转安卓接口转换线
  11. 提升进程权限的几个常用函数
  12. 为什么使用MATLAB的imnoise函数添加高斯噪声时要将方差除以255^2
  13. 苹果手机如何上传文件到服务器,有限条件下,如何将IPhone手机照片传到Windows电脑中?...
  14. Xilinx 文件的编写
  15. php 删除redis队列,php redis队列操作
  16. 计算机网络题库与答案西电,西电计算机网络期末试题.doc
  17. python 检查是否为数字(包括正负数、浮点数)
  18. 深度学习 花书中的概念——百晓生知识处理库自动抽取
  19. 计算机毕业设计Android网约车拼车打车叫车系统APP
  20. 十年后再读《轻公司》

热门文章

  1. 2021年中国互联网广告市场规模、竞争格局与发展趋势分析,行业发展稳中向好「图」
  2. ps -ef中的e、f是什么含义
  3. 嵌套/双层循环中的continue和break详解
  4. 好东西,就要一起分享。
  5. 【技术类】【ArcGIS对国产卫星的支持2:高分一号卫星】篇5、实时表观反射率产品生产
  6. HTML 导航栏标签切换
  7. ruby on rails win下安装
  8. 【Node.js】初识Node.js
  9. 科比投篮预测——可视化与探索性数据分析(二)
  10. 【转】最浅显的LDAP介绍