LRU全稱是Least Recently Used,即最近最久未使用的意思。LRU算法的設計原則是:如果一個數據在最近一段時間沒有被訪問到,那么在將來它被訪問的可能性也很小。是緩存中一種常見的機制。下圖展示了邏輯頁面緩存的訪問情況
以下是代碼實現:
public class LRUPageFrame { private static class Node { Node prev; Node next; int pageNum; Node() { } } private int capacity; private int currentSize; private Node first;// 鏈表頭 private Node last;// 鏈表尾 public LRUPageFrame(int capacity) { this.currentSize = 0; this.capacity = capacity; } /** * 獲取緩存中對象 * * @param key * @return */ public void access(int pageNum) { Node node = find(pageNum); //在該隊列中存在, 則提到隊列頭 if (node != null) { moveExistingNodeToHead(node); } else{ node = new Node(); node.pageNum = pageNum; // 緩存容器是否已經超過大小. if (currentSize >= capacity) { removeLast(); } addNewNodetoHead(node); } } private void addNewNodetoHead(Node node) { if(isEmpty()){ node.prev = null; node.next = null; first = node; last = node; } else{ node.prev = null; node.next = first; first.prev = node; first = node; } this.currentSize ++; } private Node find(int data){ Node node = first; while(node != null){ if(node.pageNum == data){ return node; } node = node.next; } return null; } /** * 刪除鏈表尾部節點 表示 刪除最少使用的緩存對象 */ private void removeLast() { Node prev = last.prev; prev.next = null; last.prev = null; last = prev; this.currentSize --; } /** * 移動到鏈表頭,表示這個節點是最新使用過的 * * @param node */ private void moveExistingNodeToHead(Node node) { if (node == first) { return; } else if(node == last){ //當前節點是鏈表尾, 需要放到鏈表頭 Node prevNode = node.prev; prevNode.next = null; last.prev = null; last = prevNode; } else{ //node 在鏈表的中間, 把node 的前后節點連接起來 Node prevNode = node.prev; prevNode.next = node.next; Node nextNode = node.next; nextNode.prev = prevNode; } node.prev = null; node.next = first; first.prev = node; first = node; } private boolean isEmpty(){ return (first == null) && (last == null); } }
代碼還有很多不足的地方,希望大家多多指正。