算法 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、输出

 

posted @ 2021-07-27 14:04  无名之士  阅读(118)  评论(0编辑  收藏  举报