package main;
import (
"container/list"
"errors"
"sync"
"fmt"
"encoding/json"
)
//LRU(Least recently used)最近最少使用,算法根據數據的歷史訪問記錄來進行淘汰數據
//核心思想是"如果數據最近被訪問過,那么將來被訪問的幾率也更高"
//常見的實現方式是用一個鏈表保存數據
//1. 新數據插入到鏈表頭部
//2. 每當緩存命中(即緩存數據被訪問),則將數據移到鏈表頭部
//3. 當鏈表滿的時候,將鏈表尾部的數據丟棄
type cacheItem struct {
Key string;
Val interface{};
}
type LRU struct {
//最大存儲數量
maxNum int;
//當前存儲數量
curNum int;
//鎖,保證數據一致性
mutex sync.Mutex;
//鏈表
data *list.List;
}
//添加數據
func (l *LRU) add(key string, value interface{}) error {
//判斷key是否存在
if e, _ := l.exist(key); e {
return errors.New(key + "已存在");
}
//判斷當前存儲數量與最大存儲數量
if l.maxNum == l.curNum {
//鏈表已滿,則刪除鏈表尾部元素
l.clear();
}
l.mutex.Lock();
l.curNum++;
//json序列化數據
data, _ := json.Marshal(cacheItem{key, value});
//把數據保存到鏈表頭部
l.data.PushFront(data);
l.mutex.Unlock();
return nil;
}
//設置數據
func (l *LRU) set(key string, value interface{}) error {
e, item := l.exist(key);
if !e {
return l.add(key, value);
}
l.mutex.Lock();
data, _ := json.Marshal(cacheItem{key, value});
//設置鏈表元素數據
item.Value = data;
l.mutex.Unlock();
return nil;
}
//清理數據
func (l *LRU) clear() interface{} {
l.mutex.Lock();
l.curNum--;
//刪除鏈表尾部元素
v := l.data.Remove(l.data.Back());
l.mutex.Unlock();
return v;
}
//獲取數據
func (l *LRU) get(key string) interface{} {
e, item := l.exist(key);
if !e {
return nil;
}
l.mutex.Lock();
//數據被訪問,則把元素移動到鏈表頭部
l.data.MoveToFront(item);
l.mutex.Unlock();
var data cacheItem;
json.Unmarshal(item.Value.([]byte), &data);
return data.Val;
}
//刪除數據
func (l *LRU) del(key string) error {
e, item := l.exist(key);
if !e {
return errors.New(key + "不存在");
}
l.mutex.Lock();
l.curNum--;
//刪除鏈表元素
l.data.Remove(item);
l.mutex.Unlock();
return nil;
}
//判斷是否存在
func (l *LRU) exist(key string) (bool, *list.Element) {
var data cacheItem;
//循環鏈表,判斷key是否存在
for v := l.data.Front(); v != nil; v = v.Next() {
json.Unmarshal(v.Value.([]byte), &data);
if key == data.Key {
return true, v;
}
}
return false, nil;
}
//返回長度
func (l *LRU) len() int {
return l.curNum;
}
//打印鏈表
func (l *LRU) print() {
var data cacheItem;
for v := l.data.Front(); v != nil; v = v.Next() {
json.Unmarshal(v.Value.([]byte), &data);
fmt.Println("key:", data.Key, " value:", data.Val);
}
}
//創建一個新的LRU
func LRUNew(maxNum int) *LRU {
return &LRU{
maxNum: maxNum,
curNum: 0,
mutex: sync.Mutex{},
data: list.New(),
};
}
func main() {
lru := LRUNew(5);
lru.add("1111", 1111);
lru.add("2222", 2222);
lru.add("3333", 3333);
lru.add("4444", 4444);
lru.add("5555", 5555);
lru.print();
//get成功后,可以看到3333元素移動到了鏈表頭
fmt.Println(lru.get("3333"));
lru.print();
//再次添加元素,如果超過最大數量,則刪除鏈表尾部元素,將新元素添加到鏈表頭
lru.add("6666", 6666);
lru.print();
lru.del("4444");
lru.print();
lru.set("2222", "242424");
lru.print();
}