当前位置: 首页 > news >正文

C# 实现Lru缓存

C# 实现Lru缓存

LRU 算法全称是最近最少使用算法(Least Recently Use),是一种简单的缓存策略。
通常用在对象池等需要频繁获取但是又需要释放不用的地方。

代码实现的基本原理就是使用链表,当某个元素被访问时(Get或Set)就将该元素放到链表的头部或者尾部(根据用户自己定义规则即可)当达到了缓存的最大容量时对最不常使用的元素进行移除(移除的时候可以定义一系列的规则,用于判读如何移除,是否移除)

下面直接贴出来代码供大家参考

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;namespace ET
{public class LruCache<TKey, TValue>: IEnumerable<KeyValuePair<TKey, TValue>>{private const int DEFAULT_CAPACITY = 255;private int capacity;private ReaderWriterLockSlim locker;private Dictionary<TKey, TValue> dictionary;private LinkedList<TKey> linkedList;private Func<TKey, TValue, bool> checkCanPopFunc;private Action<TKey, TValue> popCb;public LruCache(): this(DEFAULT_CAPACITY){}public LruCache(int capacity){this.locker = new ReaderWriterLockSlim();this.capacity = capacity > 0? capacity : DEFAULT_CAPACITY;this.dictionary = new Dictionary<TKey, TValue>(DEFAULT_CAPACITY);this.linkedList = new LinkedList<TKey>();}/// <summary>/// 设置检测什么条件可以释放/// </summary>/// <param name="func"></param>public void SetCheckCanPopCallBack(Func<TKey, TValue, bool> func){this.checkCanPopFunc = func;}/// <summary>/// 设置如何释放/// </summary>/// <param name="action"></param>public void SetPopCallBack(Action<TKey, TValue> action){this.popCb = action;}public TValue this[TKey t]{get{if (TryGet(t, out TValue val))return val;throw new ArgumentException();}set{Set(t,value);}}public bool TryGet(TKey key, out TValue value){this.locker.EnterUpgradeableReadLock();try{bool b = this.dictionary.TryGetValue(key, out value);if (b){this.locker.EnterWriteLock();try{this.linkedList.Remove(key);this.linkedList.AddFirst(key);}finally{this.locker.ExitWriteLock();}}return b;}finally{this.locker.ExitUpgradeableReadLock();}}public void Set(TKey key, TValue value){this.locker.EnterWriteLock();try{if (this.checkCanPopFunc != null)this.MakeFreeSpace();this.dictionary[key] = value;this.linkedList.Remove(key);this.linkedList.AddFirst(key);//没有设置检测释放条件的话,容量超载了就移除if (this.checkCanPopFunc == null && this.linkedList.Count > this.capacity){this.dictionary.Remove(this.linkedList.Last.Value);this.linkedList.RemoveLast();}}finally{this.locker.ExitWriteLock();}}public Dictionary<TKey, TValue> GetAll(){return this.dictionary;}public void Remove(TKey key){this.locker.EnterWriteLock();try{this.dictionary.Remove(key);this.linkedList.Remove(key);}finally{this.locker.ExitWriteLock();}}public bool TryOnlyGet(TKey key, out TValue value){bool b = this.dictionary.TryGetValue(key, out value);return b;}public bool ContainsKey(TKey key){this.locker.EnterReadLock();try{return this.dictionary.ContainsKey(key);}finally{this.locker.ExitReadLock();}}public int Count{get{this.locker.EnterReadLock();try{return this.dictionary.Count;}finally{this.locker.ExitReadLock();}}}public int Capacity{get{this.locker.EnterReadLock();try{return this.capacity;}finally{this.locker.ExitReadLock();}}set{this.locker.EnterUpgradeableReadLock();try{if (value > 0 && this.capacity != value){this.locker.EnterWriteLock();try{this.capacity = value;while (this.linkedList.Count > this.capacity){this.linkedList.RemoveLast();}}finally{this.locker.ExitWriteLock();}}}finally{this.locker.ExitUpgradeableReadLock();}}}public ICollection<TKey> Keys{get{this.locker.EnterReadLock();try{return this.dictionary.Keys;}finally{this.locker.ExitReadLock();}}}public ICollection<TValue> Values{get{this.locker.EnterReadLock();try{return this.dictionary.Values;}finally{this.locker.ExitReadLock();}}}public void Clear(){this.dictionary.Clear();this.linkedList.Clear();}private void MakeFreeSpace(){LinkedListNode<TKey> node = this.linkedList.Last;//检测最不常用的10个int max_check_free_times = 10; //最大检测空闲次数int cur_check_free_time = 0; //当前检测空闲次数while (this.linkedList.Count + 1 > this.capacity){if (node == null)break;LinkedListNode<TKey> tuple_prev = node.Previous;if (this.checkCanPopFunc == null || this.checkCanPopFunc(node.Value, this.dictionary[node.Value])){//可以释放var value = this.dictionary[node.Value];this.dictionary.Remove(node.Value);this.linkedList.RemoveLast();this.popCb?.Invoke(node.Value, value);}else{cur_check_free_time++;if (cur_check_free_time >= max_check_free_times){break;}}node = tuple_prev;}}public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator(){foreach (var item in this.dictionary){yield return item;}}IEnumerator IEnumerable.GetEnumerator(){foreach (var item in this.dictionary){yield return item;}}}
}
http://www.lryc.cn/news/260573.html

相关文章:

  • 牛客网BC107矩阵转置
  • 协作办公原来如此简单?详解 ONLYOFFICE 协作空间 2.0 更新
  • 2023年国赛高教杯数学建模A题定日镜场的优化设计解题全过程文档及程序
  • c/c++ 结构体、联合体、枚举
  • stl模板库成员函数重载类型混肴编译不通过解决方法
  • MySQL——表的约束
  • cordic 算法学习记录
  • 【STM32】电机驱动
  • csp 如此编码 C语言(回归唠嗑版)
  • 或许是全网最全的延迟队列
  • C语言结构体小项目之通讯录代码实现+代码分析
  • tp5 rewrite nginx重写
  • .NET 反射优化的经验分享
  • 使用opencv的Sobel算子实现图像边缘检测
  • 亿欧网首届“元创·灵镜”科技艺术节精彩纷呈,实在智能AI Agent智能体展现硬核科技图景
  • 宝塔面板快速搭建本地网站结合内网穿透实现远程访问【无需公网IP】
  • css的Grid布局
  • Python接口测试框架选择之pytest+yaml+Allure!
  • 03-详解Nacos注册中心的配置步骤和功能
  • 微服务学习:Nacos微服务架构中的服务注册、服务发现和动态配置Nacos下载
  • 逆向经历回顾总结
  • 企业IT安全:内部威胁检测和缓解
  • Linux 服务器较为强大的运维及管理脚本实现(支援:本机线上操作)
  • 【数据结构】插入排序,希尔排序,选择排序,堆排序,冒泡排序
  • MyBatis--07--启动过程分析、SqlSession安全问题、拦截器
  • Qt基础之四十二:QMap、QHash的实现原理和性能对比
  • 虚幻学习笔记12—C++类的实例化
  • 【《漫画算法》笔记】快速排序
  • C++如何通过调用ffmpeg接口对H265文件进行编码和解码
  • 8位LED流水灯设计