• LRU算法


    引至【想不到!面试官问我:Redis 内存满了怎么办?】,本文只关注其中的LRU算法

    LRU(Least Recently Used),即最近最少使用,是一种缓存置换算法。在使用内存作为缓存的时候,缓存的大小一般是固定的。当缓存被占满,这个时候继续往缓存里面添加数据,就需要淘汰一部分老的数据,释放内存空间用来存储新的数据。这个时候就可以使用LRU算法。其核心思想是:如果一个数据在最近一段时间没有被用到,那么将来被使用到的可能性也很小,所以就可以被淘汰掉。

    使用java实现一个简单的LRU算法

    主要思想:LRU内部实现一个Node<k,v>类,该类包含key、value,前一节点pre和后一节点next四个属性;LRU中包含一个Map<k, Node<k, v>> nodeMap的缓存map,包含所有的数据,哨兵 Node<k, v> head和 Node<k, v> tail标注链表的头部和尾部。当存入数据时(先判断LRU是否已超长,如果超长则需要删除数据)判断nodeMap是否包含该节点,如果不包含,则将该节点添加至nodeMap中,并将该节点插入至head后(即该节点pre设置为head,head节点的next设置为当前节点,该节点的next设置为head节点的的next);如果包含该数据,则需要将该node从原链表中删除,然后再将该数据插入至head后即可(将该节点的pre设置为head,head节点的next设置为当前节点)。当数据被get时,也需要先将该node从原链表中删除,然后再将该数据插入至head后(将该节点的pre设置为head,head节点的next设置为当前节点),即实现了LRU.

      1 public class LRUCache<k, v> {
      2     //容量
      3     private int capacity;
      4     //当前有多少节点的统计
      5     private int count;
      6     //缓存节点
      7     private Map<k, Node<k, v>> nodeMap;
      8     private Node<k, v> head;
      9     private Node<k, v> tail;
     10 
     11     public LRUCache(int capacity) {
     12         if (capacity < 1) {
     13             throw new IllegalArgumentException(String.valueOf(capacity));
     14         }
     15         this.capacity = capacity;
     16         this.nodeMap = new HashMap<>();
     17         //初始化头节点和尾节点,利用哨兵模式减少判断头结点和尾节点为空的代码
     18         Node headNode = new Node(null, null);
     19         Node tailNode = new Node(null, null);
     20         headNode.next = tailNode;
     21         tailNode.pre = headNode;
     22         this.head = headNode;
     23         this.tail = tailNode;
     24     }
     25 
     26     public void put(k key, v value) {
     27         Node<k, v> node = nodeMap.get(key);
     28         if (node == null) {
     29             if (count >= capacity) {
     30                 //先移除一个节点
     31                 removeNode();
     32             }
     33             node = new Node<>(key, value);
     34             //添加节点
     35             addNode(node);
     36         } else {
     37             //移动节点到头节点
     38             moveNodeToHead(node);
     39         }
     40     }
     41 
     42     public Node<k, v> get(k key) {
     43         Node<k, v> node = nodeMap.get(key);
     44         if (node != null) {
     45             moveNodeToHead(node);
     46         }
     47         return node;
     48     }
     49 
     50     private void removeNode() {
     51         Node node = tail.pre;
     52         //从链表里面移除
     53         removeFromList(node);
     54         nodeMap.remove(node.key);
     55         count--;
     56     }
     57 
     58     private void removeFromList(Node<k, v> node) {
     59         Node pre = node.pre;
     60         Node next = node.next;
     61 
     62         pre.next = next;
     63         next.pre = pre;
     64 
     65         node.next = null;
     66         node.pre = null;
     67     }
     68 
     69     private void addNode(Node<k, v> node) {
     70         //添加节点到头部
     71         addToHead(node);
     72         nodeMap.put(node.key, node);
     73         count++;
     74     }
     75 
     76     private void addToHead(Node<k, v> node) {
     77         Node next = head.next;
     78         next.pre = node;
     79         node.next = next;
     80         node.pre = head;
     81         head.next = node;
     82     }
     83 
     84     public void moveNodeToHead(Node<k, v> node) {
     85         //从链表里面移除
     86         removeFromList(node);
     87         //添加节点到头部
     88         addToHead(node);
     89     }
     90 
     91     class Node<k, v> {
     92         k key;
     93         v value;
     94         Node pre;
     95         Node next;
     96 
     97         public Node(k key, v value) {
     98             this.key = key;
     99             this.value = value;
    100         }
    101     }
    102 }
  • 相关阅读:
    ffmpeg+EasyDSS流媒体服务器实现稳定的rtmp推流直播
    ffmpeg+EasyDSS流媒体服务器实现稳定的rtmp推流直播
    EasyPlayerPro安卓流媒体播放器实现Android H.265硬解码流程
    EasyPlayerPro安卓流媒体播放器实现Android H.265硬解码流程
    EasyPlayer RTSP安卓Android播放器架构简析
    EasyPlayer RTSP安卓Android播放器架构简析
    解决RTMP推送时间戳问题引起HLS切片不均匀导致手机浏览器播放卡顿的问题
    解决RTMP推送时间戳问题引起HLS切片不均匀导致手机浏览器播放卡顿的问题
    EasyPusher/EasyDarwin支持H.265 RTSP/RTP直播推流与分发播放
    EasyPusher/EasyDarwin支持H.265 RTSP/RTP直播推流与分发播放
  • 原文地址:https://www.cnblogs.com/Java-Script/p/11639488.html
Copyright © 2020-2023  润新知