• 算法 LRU


    在Linux内存管理系统中,为了解决内存不够用问题,使用了分页存储。

    即将一个程序分为若干个大小为4K(默认)的页,程序运行时需要什么就将其加载到内存中,这样可以使有限的内存运行更多的进程。然而内存还是会出现已满的时候,所以此时加载的页该如何分配?

    于是Linux使用了LRU算法:

      将最近最少使用的页从内存移动到磁盘中,将新的页加入内存。

      关键数据结构:哈希表+双向链表。 可以在O(1)时间复杂度找到需要移动的元素。并且在O(1)时间复杂度将元素移除。

    示例代码:

      1、定义节点类Node:

    public class Node<k,v> {
        k key;
        v value;
    
        Node<k, v> next;
        Node<k, v> prev;
    
        public Node() {
        }
    
        public Node(k key, v value) {
            this.key = key;
            this.value = value;
        }
    
        @Override
        public String toString() {
            return "Node{" +
                    "key=" + key +
                    ", value=" + value +
                    '}';
        }
    }

      2、定义哈希双向链表:

    import java.util.HashMap;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LRUHashList<k,v> {
        Node<k, v> head = new Node<>();
        Node<k, v> tail= new Node<>();
    
        private final int maxcache;
        private volatile int size;
        private HashMap<k, Node<k,v>> hashMap = new HashMap<>();
        ReentrantLock reentrantLock = new ReentrantLock();
    
        public LRUHashList(int maxcache) {
            this.maxcache = maxcache;
            head.next = tail;
            tail.prev = head;
        }
    
        private void addNode(Node<k,v> node){
            node.next = head.next;
            node.prev = head;
            head.next.prev = node;
            head.next = node;
        }
    
        private void delNode(Node<k,v> node){
            node.prev.next = node.next;
            node.next.prev = node.prev;
            node.prev = null;
            node.next = null;
        }
    
        public void put(k key, v val){
            reentrantLock.lock();
            Node<k,v> newnode = hashMap.get(key);
            if(newnode == null){
                Node<k, v> node = new Node<>(key, val);
                if(size < maxcache){
                    size++;
                }else {
                    hashMap.remove(tail.prev.key);
                    delNode(tail.prev);
                }
                addNode(node);
                hashMap.put(key, node);
            }else{
                newnode.value = val;
                delNode(newnode);
                addNode(newnode);
            }
            reentrantLock.unlock();
        }
    
        public Node<k,v> get(k key){
            reentrantLock.lock();
            Node<k, v> node = hashMap.get(key);
            if(node != null){
                delNode(node);
                addNode(node);
            }
            reentrantLock.unlock();
            return node;
        }
    
        @Override
        public String toString() {
            return "LRUHashList{" +
                    "hashMap=" + hashMap +
                    '}';
        }
    
        public int getSize(){
            return this.size;
        }
    
        public static void main(String[] args) {
            LRUHashList<Integer,String> list = new LRUHashList<Integer, String>(2);
            int count = 10;
            CountDownLatch countDownLatch = new CountDownLatch(count);
    
    
            for (int i = 0; i < count; i++) {
                new Thread(()->{
                    int j = (int) (Math.random()*10);
                    list.put(j,"33");
                    System.out.println(Thread.currentThread().getName() + " " +  j);
                    countDownLatch.countDown();
                }, "00"+i).start();
    //            try {
    //                Thread.sleep(1000);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
            }
    
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(" " + list.getSize() + list);
        }
    }

      3、输出

  • 相关阅读:
    设置ios中imageView图片自适应,
    IOS应用之间调用
    XCode debug中添加查找debug和控制台的办法
    初学Java scirpt(判断、循环语句)
    Java Script 字符串操作
    初学 Java Script (算数运算及逻辑术语)
    Ubuntu 配置JDK
    SQL Server 跨库复制表方法小笔记
    Ubuntu 重装 mysql
    Java Script 数组操作
  • 原文地址:https://www.cnblogs.com/unknown6248/p/15065584.html
Copyright © 2020-2023  润新知