本地缓存类(LRU Cache),喜欢的朋友拿去用
这是一个固定长度的双向链表,没有闭合,当然是起初没写成闭合的。
怎么缓存的呢? 就是比如 长度是3000,你缓存一篇文章 就放进去一个, 如果你从里面获取一个A,则A被提到链表的头部,再放入一个B,则B在头部, 其他的就会靠后排。如果缓存的数量超过的3000,再缓存新的时候会踢掉尾部的那个。因为那个用的次数很少。
public class CacheList<T> where T : class { public class Item { public string Key { get ; set ; } public T Value { get ; set ; } public Item Left { get ; set ; } public Item Right { get ; set ; } public Item( string key, T value) { Key = key; Value = value; } } private readonly static object _locked = new object (); private readonly IDictionary< string , Item> _dict; public int Length { get ; private set ; } public CacheList( int maxLength) { _dict = new Dictionary< string , Item>(); Length = maxLength; } private Item _first; private Item _last; public bool HasKey( string key) { lock (_locked) { return _dict.ContainsKey(key); } } public void Add( string key, T value) { var item = new Item(key, value); lock (_locked) { if (_dict.Count == 0) { _last = _first = item; } else if (_dict.Count == 1) { _last = _first; _first = item; _last.Left = _first; _first.Right = _last; } else { item.Right = _first; _first.Left = item; _first = item; } if (_dict.Count >= Length) { _last.Left.Right = null ; _dict.Remove(_last.Key); _last = _last.Left; } _dict.AddValue(key, item); } } public T Get( string key) { Item item = null ; lock (_locked) { _dict.TryGetValue(key, out item); } if (item == null ) return null ; lock (_locked) { if (_dict.Count == 1) { return _first.Value; } if (item.Left != null ) { item.Left.Right = item.Right; } else { return item.Value; } if (item.Right != null ) { item.Right.Left = item.Left; } else { _last.Left.Right = null ; _last = _last.Left; } item.Left = null ; item.Right = _first; _first.Left = item; _first = item; } return item.Value; } public void Remove( string key) { Item item = null ; lock (_locked) { _dict.TryGetValue(key, out item); } if (item == null ) return ; lock (_locked) { if (item.Left != null ) { item.Left.Right = item.Right; } else { _first = item.Right; } if (item.Right != null ) { item.Right.Left = item.Left; } else { _last = item.Left; } _dict.Remove(key); } } } |
public class ArticleCacheProvider { private static readonly CacheList<Article> CacheList; private static string GetCacheKey( string fileNameOrArticleId, int blogId) { return ( "article_" + fileNameOrArticleId + "_" + blogId).ToLower(); } static ArticleCacheProvider() { CacheList = new CacheList<Article>(3000); } public static Article Get( string fileNameOrArticleId, int blogId) { return CacheList.Get(GetCacheKey(fileNameOrArticleId, blogId)); } public static void Set(Article entity) { //如果文章有别名,则存2份key,filename和articleId都可以获取缓存实体 if (entity.FileName != entity.ArticleId.ToString()) { CacheList.Add(GetCacheKey(entity.ArticleId.ToString(), entity.BlogId), entity); } CacheList.Add(GetCacheKey(entity.FileName, entity.BlogId), entity); } public static void Remove( string fileNameOrArticleId, int blogId) { CacheList.Remove(GetCacheKey(fileNameOrArticleId, blogId)); } public static bool HasArticle( string fileNameOrArticleId, int blogId) { return CacheList.HasKey(GetCacheKey(fileNameOrArticleId, blogId)); } } |
用处?有什么用处呢?,其实就是缓存起来呗,避免一条热门记录的反复查询。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?