Mysql 主從常遇問題
阿新 • • 發佈:2022-12-06
文章目錄
1、記憶體空間有限,當快取滿的時候,如何淘汰快取?
2、實現LRU demo
- 使用Java容器LinkedHashMap
- 雜湊表(HashMap)+雙向連結串列
1、記憶體空間有限,當快取滿的時候,如何淘汰快取?
FIFO(First In First Out)先進先出
LFU(Least Frequently Used)最不經常使用
LRU(Least Recently Used)最近最少使用
2、實現LRU demo
1、使用Java容器LinkedHashMap
LinkedHashMap本身就具有LRU演算法的特性
class LRUCache { privateMap<Integer, Integer> cacheMap = null; public LRUCache(int capacity) { // 引數設定true,當removeEldestEntry()返回true,則刪除最舊的資料 cacheMap = new LinkedHashMap<Integer, Integer>(capacity,0.75F,true){ @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size() > capacity; } }; } public int get(int key) { return cacheMap.getOrDefault(key, -1); } public void put(int key, int value) { cacheMap.put(key, value); } }
2、雜湊表(HashMap)+雙向連結串列
維護一個雙向連結串列,靠近連結串列尾部的結點是越早訪問的,靠近頭部的節點是最近訪問的。
如果此資料之前已經被快取在連結串列中了,我們遍歷得到這個資料對應的結點,並將其從原來的位置刪除,然後再插入到連結串列的頭部。
如果此資料沒有在快取連結串列中,又可以分為兩種情況:
如果此時快取未滿,則將此結點直接插入到連結串列的頭部
如果此時快取已滿,則連結串列尾結點刪除,將新的資料結點插入連結串列的頭部。
class LRUCache2 { // 當前快取容量 private int size; // 限制最大快取容量 private int capacity; // 定義偽頭尾節點 private Node head; private Node tail; // 定義HashMap儲存資料 private Map<Integer, Node> cache = new HashMap(); // 初始化操作 public LRUCache2(int capacity) { size = 0; this.capacity = capacity; // 初始化頭尾節點 head = new Node(); tail = new Node(); // 讓頭尾節點相聯 head.next = tail; tail.pre = head; } public int get(int key) { Node node = cache.get(key); // 不存在返回-1 if (null == node) { return -1; } // 存在返回值,並且將當前節點移動到頭 moveNodeHead(node); return node.value; } public void put(int key, int value) { Node node = cache.get(key); // 不存在則插入,插入後判斷當前容量是否大於限制最大容量 if (null == node) { Node newNode = new Node(key, value); cache.put(key, newNode); // 放入連結串列頭部 addNodeHead(newNode); size++; if (size > capacity) { // 刪除尾結點 Node tail = removeNodeTail(); cache.remove(tail.key); } } else { // 存在則覆蓋value,並且將當前節點移動到頭 node.value = value; moveNodeHead(node); } } // 放入連結串列的頭部 private void addNodeHead(Node node) { // 當前頭節點的下一個節點的pre和當前節點連線 head.next.pre = node; // node.next = head.next; // head.next = node; node.pre = head; } // 將節點移動到連結串列的頭部 private void moveNodeHead(Node node) { node.pre.next = node.next; node.next.pre = node.pre; addNodeHead(node); } // 刪除連結串列的尾結點 private Node removeNodeTail() { Node tailNode = tail.pre; tailNode.pre.next = tailNode.next; tailNode.next.pre = tailNode.pre; return tailNode; } // 定義一個雙向連結串列,實際的快取 class Node { private int key; private int value; private Node pre; private Node next; public Node() { } public Node(int key, int value) { this.key = key; this.value = value; } } }