在网上找到网友中的方法,将其修改整理后,实现了缓存量控制以及时间控制,如果开启缓存时间控制,会降低效率。

定义枚举,移除时使用

public enum RemoveType
    {
        [Description("超时移除")]
        TimeOut,
        [Description("超量移除")]
        Capacity
    }

定义委托,移除时使用

public delegate void RemoveKV<Tkey, TValue>(string cacheName, RemoveEntity<Tkey, TValue> entity);

定义缓存类

public class LRUCache<TKey, TValue>
    {
       const  int DEFAULT_CAPACITY = int.MaxValue;

private int _capacity;
        private  ReaderWriterLockSlim locker;
        private  IDictionary<TKey, TValue> dictionary;//数据
        private LinkedList<TKey> linkedList;//控制Key的数据
        private Dictionary<TKey, LinkedListNode<TKey>> dicLinkIndex = null;//控制删除
        private Dictionary<TKey, long> dicRefresh = null;//使用时间
        private volatile bool isCheckTime = false;//设置是否监测缓存的时间长度
        private  long cacheTime = 600;//10分钟
        private volatile bool isCheckThread = false;//检查线程启动
        private long checkTicks = 0;//换算后的时间
        private BlockingCollection<RemoveEntity<TKey, TValue>> removeEntities = null;
        public event RemoveKV<TKey, TValue> RemoveEntitiesEvent = null;//移除通知
        private DateTime checkTime = DateTime.Now;//结束监测的时间

/// <summary>
        /// 设置缓存的时间长度,当前按照秒算
        /// 设置时间自动设置属性IsCacheCheckTime=true
        /// </summary>
        public long CacheTime { get { return cacheTime; } set { cacheTime = value;isCheckTime = true; countTime(); } }

/// <summary>
        /// 是否监测时间
        /// </summary>
        public bool IsCacheCheckTime { get { return isCheckTime; } set { isCheckTime = value; countTime(); } }

/// <summary>
        /// cache名称
        /// </summary>
        public string CacheName { get; set; }

public LRUCache() : this(DEFAULT_CAPACITY) { }

public LRUCache(int capacity)
        {
            locker = new ReaderWriterLockSlim();
            _capacity = capacity > 0 ? capacity : DEFAULT_CAPACITY;
            dictionary = new Dictionary<TKey, TValue>();
            linkedList = new LinkedList<TKey>();
            dicLinkIndex = new Dictionary<TKey, LinkedListNode<TKey>>();
            dicRefresh = new Dictionary<TKey, long>();
            removeEntities = new BlockingCollection<RemoveEntity<TKey, TValue>>(1000);
           
            countTime();
            RemoveNotice();
        }

/// <summary>
        /// 换算时间;
        /// 将秒转换成ticks个数
        /// </summary>
        private void countTime()
        {
           
            checkTicks = 10000000 * cacheTime;
        }

/// <summary>
        /// 更新时间
        /// </summary>
        /// <param name="key"></param>
        private void Refresh(TKey key)
        {
            dicRefresh[key] = DateTime.Now.Ticks;
            if(!isCheckTime)
            {
                return;
            }
            if(!isCheckThread)
            {
                isCheckThread = true;
                Task.Factory.StartNew(() =>
                {
                 
                    double wait = (DateTime.Now - checkTime).TotalSeconds;
                    if(wait<cacheTime)
                    {
                        //如果上次监测到本次监测还未到设置的保持时间,
                        //则等待该时间差后再检查
                        double sleep = ((double)cacheTime-wait) * 1000+1;
                        Thread.Sleep((int)sleep);
                    }
                    locker.EnterWriteLock();
                    try
                    {
                        LinkedListNode<TKey> last = null;
                        long tick;
                        long curTick = DateTime.Now.Ticks;
                        last = linkedList.Last;//重后往前找
                        while (last != null)
                        {
                            if (dicRefresh.TryGetValue(last.Value, out tick))
                            {
                                if ((curTick - tick) > checkTicks)
                                {
                                    dicLinkIndex.Remove(last.Value);
                                    dicRefresh.Remove(last.Value);
                                    linkedList.RemoveLast();
                                    RemoveEntity<TKey, TValue> entity = new RemoveEntity<TKey, TValue>() { Key = last.Value, Value = dictionary[last.Value], RemoveType= RemoveType.TimeOut };
                                    removeEntities.Add(entity);
                                    dictionary.Remove(last.Value);
                                }
                                else
                                {
                                    break;
                                }
                            }
                            last = linkedList.Last;
                        }
                    }
                    finally { locker.ExitWriteLock(); }
                    isCheckThread = false;
                    checkTime = DateTime.Now;
                });
            }
        }

private void RemoveNotice()
        {
            Task.Factory.StartNew(() =>
            {
                while(true)
                {

RemoveEntity<TKey, TValue> item=null;
                    if(removeEntities.TryTake(out item,500))
                    {
                        if(this.RemoveEntitiesEvent != null)
                        {
                            RemoveEntitiesEvent(CacheName, item);
                        }
                    }
                }
            });
        }

public void Set(TKey key, TValue value)
        {
            locker.EnterWriteLock();
            try
            {
                  dictionary[key] = value;
                  LinkedListNode<TKey> item = null;
                 if(dicLinkIndex.TryGetValue(key,out item))
                {
                    linkedList.Remove(item);
                }
                 dicLinkIndex[key]= linkedList.AddFirst(key);
                 
                if (linkedList.Count > _capacity)
                {
                    dictionary.Remove(linkedList.Last.Value);
                    dicLinkIndex.Remove(linkedList.Last.Value);
                    linkedList.RemoveLast();
                    dicRefresh.Remove(linkedList.Last.Value);
                    RemoveEntity<TKey, TValue> entity = new RemoveEntity<TKey, TValue>() { Key = linkedList.Last.Value, Value = dictionary[linkedList.Last.Value], RemoveType = RemoveType.Capacity };
                    removeEntities.Add(entity);
                    dictionary.Remove(linkedList.Last.Value);
                }
                Refresh(key);
            }
            finally { locker.ExitWriteLock(); }
          
        }

public bool TryGet(TKey key, out TValue value)
        {
            locker.EnterUpgradeableReadLock();
            try
            {
                bool b = dictionary.TryGetValue(key, out value);
                if (b)
                {
                    locker.EnterWriteLock();
                    try
                    {
                        linkedList.Remove(key);
                        linkedList.AddFirst(key);
                    }
                    finally { locker.ExitWriteLock(); }

}
                Refresh(key);
                return b;
            }
            catch { throw; }
            finally { locker.ExitUpgradeableReadLock(); }
        }
        public void Clear()
        {
            locker.EnterWriteLock();
            try
            {
                dictionary.Clear();
                linkedList.Clear();
                dicRefresh.Clear();
                dicLinkIndex.Clear();
                dicRefresh.Clear();
            }
            finally
            {
                locker.ExitWriteLock();
            }
        }
        public bool Remove(TKey key)
        {
            bool isSucess = false;
            locker.EnterWriteLock();
            try
            {
                isSucess = dictionary.Remove(key);
                dicRefresh.Remove(key);
                LinkedListNode<TKey> item = null;
                if (dicLinkIndex.TryGetValue(key, out item))
                {
                    linkedList.Remove(item);
                }
            }
            finally
            {
                locker.ExitWriteLock();
            }
            return isSucess;
        }
        public bool ContainsKey(TKey key)
        {
            locker.EnterReadLock();
            try
            {
                return dictionary.ContainsKey(key);
            }
            finally { locker.ExitReadLock(); }
        }

public int Count
        {
            get
            {
                locker.EnterReadLock();
                try
                {
                    return dictionary.Count;
                }
                finally { locker.ExitReadLock(); }
            }
        }

public int Capacity
        {
            get
            {
                locker.EnterReadLock();
                try
                {
                    return _capacity;
                }
                finally { locker.ExitReadLock(); }
            }
            set
            {
                locker.EnterUpgradeableReadLock();
                try
                {
                    if (value > 0 && _capacity != value)
                    {
                        locker.EnterWriteLock();
                        try
                        {
                            _capacity = value;
                            while (linkedList.Count > _capacity)
                            {
                                linkedList.RemoveLast();
                            }
                        }
                        finally { locker.ExitWriteLock(); }
                    }
                }
                finally { locker.ExitUpgradeableReadLock(); }
            }
        }

public ICollection<TKey> Keys
        {
            get
            {
                locker.EnterReadLock();
                try
                {
                    return dictionary.Keys;
                }
                finally { locker.ExitReadLock(); }
            }
        }

public ICollection<TValue> Values
        {
            get
            {
                locker.EnterReadLock();
                try
                {
                    return dictionary.Values;
                }
                finally { locker.ExitReadLock(); }
            }
        }
    }

//最后在定一个异常的实体

public class RemoveEntity<TKey,TValue>
    {
        public TKey Key { get; set; }
        public TValue Value { get; set; }

public RemoveType RemoveType { get; set; }
    }

就完成了,测试代码

LRUCache<int, int> cache = new LRUCache<int, int>();
              cache.RemoveEntitiesEvent += Cache_RemoveEntitiesEvent;
              cache.CacheTime =3;//启动缓存时间
             Random random = new Random();
             DateTime start= DateTime.Now;
            for(int i=0;i<10000000;i++)
            {
                cache.Set(i,random.Next());
               
            }
           
            Console.WriteLine("时间:" + (DateTime.Now - start).TotalSeconds);
            Console.Read();

总共10-12秒;如果屏蔽缓存时间设置,7秒

代码已经传到GIT,地址和上一篇缓存模板一直,整合在同一个项目中。

c# LRU实现的缓存类的更多相关文章

  1. LinkedList实现基于LRU算法的缓存

    LinkedList实现基于LRU算法的缓存 2015年08月07日 18:18:45 秦江波 阅读数 2068 文章标签: java算法linkedlist缓存LRU更多 分类专栏: Java   ...

  2. ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core

    背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...

  3. 分享个 之前写好的 android 文件流缓存类,专门处理 ArrayList、bean。

    转载麻烦声明出处:http://www.cnblogs.com/linguanh/ 目录: 1,前序 2,作用 3,特点 4,代码 1,前序  在开发过程中,client 和 server 数据交流一 ...

  4. cache4j轻量级java内存缓存框架,实现FIFO、LRU、TwoQueues缓存模型

    简介 cache4j是一款轻量级java内存缓存框架,实现FIFO.LRU.TwoQueues缓存模型,使用非常方便. cache4j为java开发者提供一种更加轻便的内存缓存方案,杀鸡焉用EhCac ...

  5. (实用篇)PHP缓存类完整实例

    本文完整描述了一个简洁实用的PHP缓存类,可用来检查缓存文件是否在设置更新时间之内.清除缓存文件.根据当前动态文件生成缓存文件名.连续创建目录.缓存文件输出静态等功能.对于采用PHP开发CMS系统来说 ...

  6. php简单缓存类

    <?phpclass Cache {    private $cache_path;//path for the cache    private $cache_expire;//seconds ...

  7. ASP缓存类收集

    木鸟写的 '********************************************** ' vbs Cache类 ' ' 属性valid,是否可用,取值前判断 ' 属性name,ca ...

  8. php简单数据缓存类

    公司手机触屏站 ,由于页面图片太多,所以需要做数据缓存,就随便写一个数据缓存类. 直接贴代码 <?php/**** fianl_m@foxmail.com* 缓存类* 把数据查询出,并序列化写入 ...

  9. iOS缓存类的设计

    使用执行速度缓存的程序可以大大提高程序,设计一个简单的缓存类并不需要太复杂的逻辑. 只需要一个简单的3接口. 存款对象 以一个对象 删除对象 阅读对象 watermark/2/text/aHR0cDo ...

随机推荐

  1. c#做的查找文件夹内内容的小工具

    第一次写博客有点激动啊QAQ 来新单位,一直没活干,公司代码控制器太多,其中有很多文件夹,每次找一个控制器都老找不到,我又不愿意用VS的全局搜索,想着没事就做了个查找控制器的小工具.代码如下: 先添加 ...

  2. 再写一篇ubuntu服务器的环境配置文

    三年前写过一篇,但是环境和三年前比已经发生了比较大的变化,于是重新写一篇,自己以后再次配置也比较方便.我个人而言并没有觉得centos比ubuntu好用多少,所以继续选用ubuntu. 一.硬盘分区  ...

  3. Linux 连接 Xshell 及网络配置

    一.准备工具 在WMware上已经装有Linux系统:WMware安装CentOS7文章. xshell连接工具: 二.修改相关配置 切换到root用户下: 配置主机名(可选): #方法一:替换原主机 ...

  4. jquery.rotate.js可选抽奖次数和中奖内容的转盘抽奖demo

    需求: 最多可以抽奖5次,而且,每次只会中“2000元理财金”或者“谢谢参与”,其它的不会抽中(哈哈,果然都是套路). 效果如下: 一.页面结构: <div class="g-cont ...

  5. angular2-动画

    使用动画: import { Component, Input } from '@angular/core'; import { trigger, state, style, animate, tra ...

  6. js for in 遍历对象与数组

    遍历对象 let obj = { q:'9', w:'5', e:'2', t:'7', c:'3' } //for in 遍历对象 key为对象的属性名称,遍历属性值时用[]操作符访问 //通过[] ...

  7. Linux中怎么从root用户切换到普通用户

    su是在用户间切换,可以是从普通用户切换到root用户, test@ubuntu:~$ su Password:  root@ubuntu:/home/test# 也可以是从root用户切换到普通用户 ...

  8. dialog和dialogFragment的使用及常用问题

    今天比较懒,只是列举了一些网址 弹窗之一:dialogFragment的使用 https://blog.csdn.net/sinat_31057219/article/details/76979246 ...

  9. Android学习——AsyncTask的使用

    AsyncTask是安卓自带的异步操作类,把异步操作简化并封装好,从而可以让开发者在子线程中更方便地更新UI. AsyncTask为一个抽象类,在继承AsyncTask时需要指定如下三个泛型参数:&l ...

  10. Android学习——ViewPager的使用(三)

    这一节来介绍一下在ViewPager中常用到的一个控件,标题栏. 标题栏分为PagerTabStrip和PagerTitleStrip两种,用法类似,这里介绍第一种. 具体做法 在layout文件中的 ...