这是一个固定长度的双向链表,没有闭合,当然是起初没写成闭合的。
怎么缓存的呢? 就是比如 长度是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)); } }
用处?有什么用处呢?,其实就是缓存起来呗,避免一条热门记录的反复查询。