本地缓存类(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));
      }
  } 

用处?有什么用处呢?,其实就是缓存起来呗,避免一条热门记录的反复查询。 

posted @ 2011-03-24 14:27  君之蘭  阅读(3429)  评论(7编辑  收藏  举报