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;}}}
}
相关文章:
C# 实现Lru缓存
C# 实现Lru缓存 LRU 算法全称是最近最少使用算法(Least Recently Use),是一种简单的缓存策略。 通常用在对象池等需要频繁获取但是又需要释放不用的地方。 代码实现的基本原理就是使用链表,当某个元素被访问时(Get或…...
牛客网BC107矩阵转置
答案: #include <stdio.h> int main() {int n0, m0,i0,j0,a0,b0;int arr1[10][10]{0},arr2[10][10]{0}; //第一个数组用来储存原矩阵,第二个数组用来储存转置矩阵scanf("%d%d",&n,&m); if((n>1&&n<10)&&am…...
协作办公原来如此简单?详解 ONLYOFFICE 协作空间 2.0 更新
协作办公原来如此简单?详解 ONLYOFFICE 协作空间 2.0 更新 上周,ONLYOFFICE 的协作空间推出升级版 2.0 版本了: ONLYOFFICE 协作空间 2.0 现已发布:新增公共房间、插件、重新分配数据、RTL 界面等功能 ONLYOFFICE 协作空间是去…...
2023年国赛高教杯数学建模A题定日镜场的优化设计解题全过程文档及程序
2023年国赛高教杯数学建模 A题 定日镜场的优化设计 原题再现 构建以新能源为主体的新型电力系统,是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。 定日镜是塔式太阳能光热发电站(以下…...
c/c++ 结构体、联合体、枚举
结构体 结构体内存对齐规则: 1、结构体的第一个成员对齐到结构体变量起始位置偏移量为0的地址处 2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数:编译器默认的一个对齐数与该成员变量大小的较小值。 vs 中…...
stl模板库成员函数重载类型混肴编译不通过解决方法
stl模板库成员函数重载类型混肴编译不通过解决方法 这种方式编译不通过IsArithmetic和HasMemberList编译器存在混肴 template <typename T, typename Enable std::enable_if<IsArithmetic<T>::value>::type >static void DumpWrapper(T* filed, std::strin…...
MySQL——表的约束
目录 一.表的约束 二.空属性 编辑三.默认值 四.列描述 五.主键 1.主键 2.符合主键 六.自增长 七.唯一键 八.外键 一.表的约束 真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性&…...
cordic 算法学习记录
参考:b站教学视频FPGA:Cordic算法介绍与实现_哔哩哔哩_bilibili FPGA硬件实现加减法、移位等操作比较简单,但是实现乘除以及函数计算复杂度高且占用资源多,常见的计算三角函数/平方根的求解方式有①查找表:先把函数对应…...
【STM32】电机驱动
一、电机分类 二、直流电机的分类 1.有刷电机 2.无刷电机 3.直流减速电机 三、H桥电路 正向旋转 驱动Q1和Q4 反向旋转 驱动Q2和Q3 四、MC3386电机驱动芯片 1.基本原理图 1)前进/后退:IN1和IN2的电平顺序决定电机的正反转 2)调节速度&#…...
csp 如此编码 C语言(回归唠嗑版)
熟悉的开篇废话,最近其实在研究那个web开发这一块,导致csp联系就减少了,好久没更csp的帖子了,尽管明天就要考了,但是嘞,能看一道是一道呗对吧。 等过段时间我把web开发这一块整明白了就发帖子,…...
或许是全网最全的延迟队列
什么是延迟队列 作用:用来存储延迟消息延迟消息:生产者发送一个消息给mq,然后mq会经过一段时间(延迟时间),然后在把这个消息发送给消费者 应用场景 预定会议后,需要在预定的时间点前十分钟通…...
C语言结构体小项目之通讯录代码实现+代码分析
一、思路 1.文件 这里由于通讯录实现代码较长,因此分三个文件进行,contact.c用于实现通讯录主体代码,声明各项头文件用contact.h实现,测试用test.c 二.功能 增加联系人删除联系人修改联系人查找指定联系人排序显示通讯录的信息…...
tp5 rewrite nginx重写
tp框架,默认的访问路径是 www.xxxx.com/index.php/admin/shop/index格式的,为了方便和更规范,也看起来有逼格一些,需要将index.php去掉 无index.php就会报404 我这里是宝塔 #地址重写if (!-e $request_filename) {rewrite ^(.*)$ /index.…...
.NET 反射优化的经验分享
比如针对 GetCustomAttributes 通过反射获取属性的优化,以下例子 // dotnet run -c Release -f net7.0 --filter "*" --runtimes net7.0 net8.0public class Tests{public object[] GetCustomAttributes() => typeof(C).GetCustomAttributes(typeof(MyAttribute…...
使用opencv的Sobel算子实现图像边缘检测
1 边缘检测介绍 图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题,也是经典的技术难题之一。如何快速、精确地提取图像边缘信息,一直是国内外的研究热点,同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法…...
亿欧网首届“元创·灵镜”科技艺术节精彩纷呈,实在智能AI Agent智能体展现硬核科技图景
12月4日-10日,持续一周的首届“元创灵镜”科技艺术节在海南陵水香水湾拉开帷幕,虚实交互创造出的“海岛之镜”开幕式呈现出既真实又虚幻的未来感,融入前沿科技元素的艺术装置作品在“虚实之镜&自然生长”科技艺术展诠释着浪漫想象&#x…...
宝塔面板快速搭建本地网站结合内网穿透实现远程访问【无需公网IP】
文章目录 前言1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面 前言 宝塔面板作为简单好用的服务器运维管理面板,它支持Linux/Windows系统,我们可用它来一键配置LAMP/LNMP环境、网站、数据库、FTP等&…...
css的Grid布局
1.简单布局 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr; 布局样式 column-gap: 24px; 列间距 row-gap: 24px; 行间距 } 2.排列布局 center垂直方向居中对其 end靠下对齐 3.水平方向对齐 center居中 end靠右对齐 space-between两段对齐 4.对…...
Python接口测试框架选择之pytest+yaml+Allure!
一、为什么选择pytest? pytest完全兼容python自带的unittest pytest让单元测试更简单,能很好的管理测试用例。 对于实现接口测试的复杂场景,pytest的fixture、PDB等高阶用法都能实现需求。 入门简单,对于代码基础薄弱的团队人员…...
03-详解Nacos注册中心的配置步骤和功能
Nacos注册中心 服务注册到Nacos Nacos是SpringCloudAlibaba的组件也遵循SpringCloud中定义的服务注册和服务发现规范,因此使用Nacos与使用Eureka对于微服务来说并没有太大区别 主要差异就是依赖不同,服务地址不同 第一步: 在父工程cloud-demo模块的pom.xml文件中引入Spring…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
