c# LRU实现的缓存类
在网上找到网友中的方法,将其修改整理后,实现了缓存量控制以及时间控制,如果开启缓存时间控制,会降低效率。
定义枚举,移除时使用
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实现的缓存类的更多相关文章
- LinkedList实现基于LRU算法的缓存
LinkedList实现基于LRU算法的缓存 2015年08月07日 18:18:45 秦江波 阅读数 2068 文章标签: java算法linkedlist缓存LRU更多 分类专栏: Java ...
- ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core
背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...
- 分享个 之前写好的 android 文件流缓存类,专门处理 ArrayList、bean。
转载麻烦声明出处:http://www.cnblogs.com/linguanh/ 目录: 1,前序 2,作用 3,特点 4,代码 1,前序 在开发过程中,client 和 server 数据交流一 ...
- cache4j轻量级java内存缓存框架,实现FIFO、LRU、TwoQueues缓存模型
简介 cache4j是一款轻量级java内存缓存框架,实现FIFO.LRU.TwoQueues缓存模型,使用非常方便. cache4j为java开发者提供一种更加轻便的内存缓存方案,杀鸡焉用EhCac ...
- (实用篇)PHP缓存类完整实例
本文完整描述了一个简洁实用的PHP缓存类,可用来检查缓存文件是否在设置更新时间之内.清除缓存文件.根据当前动态文件生成缓存文件名.连续创建目录.缓存文件输出静态等功能.对于采用PHP开发CMS系统来说 ...
- php简单缓存类
<?phpclass Cache { private $cache_path;//path for the cache private $cache_expire;//seconds ...
- ASP缓存类收集
木鸟写的 '********************************************** ' vbs Cache类 ' ' 属性valid,是否可用,取值前判断 ' 属性name,ca ...
- php简单数据缓存类
公司手机触屏站 ,由于页面图片太多,所以需要做数据缓存,就随便写一个数据缓存类. 直接贴代码 <?php/**** fianl_m@foxmail.com* 缓存类* 把数据查询出,并序列化写入 ...
- iOS缓存类的设计
使用执行速度缓存的程序可以大大提高程序,设计一个简单的缓存类并不需要太复杂的逻辑. 只需要一个简单的3接口. 存款对象 以一个对象 删除对象 阅读对象 watermark/2/text/aHR0cDo ...
随机推荐
- SpringSecurity 3.2入门(2)环境搭建
由于目前Spring官方只提供Meven的下载方式,为了能以最快的速度入门使用框架,这里提供百度网盘下载链接. 注:本入门教程默认已经配置成功SpringMVC框架. 1.web.xml配置 < ...
- XML入门介绍(什么是XML及XML格式)
什么是 XML? XML 指可扩展标记语言(EXtensible Markup Language). XML 是一种很像HTML的标记语言. XML 的设计宗旨是传输数据,而不是显示数据. XML 标 ...
- C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)
萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...
- python作业-网络编程
1.什么是C/S架构? 答:C指的是client(客户端软件),S指的是Server(服务端软件) 2.互联网协议是什么?分别介绍五层协议中每一层的功能? 答:互联网的核心就是由一堆协议组成.如果把计 ...
- 2018.10.23NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 50 + (10 \sim 50)\) 实际得分:\(100 + 10 + 50\) 这可能是我打的最懵逼的一场考试没有之一.. T1两个小时才做出来也是醉了. T ...
- Angular JS例子 ng-repeat遍历输出
首先要有Angular的插件:然后才开始遍历 :<!DOCTYPE html> <html lang="en"> <head> <meta ...
- 【Linux】 静态函数库设计
一.外部函数来源-- 函数库&系统调用 二.函数库分类 静态函数库 --多份拷贝 动态函数库 --单份拷贝 区别 链接方式区别 三.函数库存放位置 Linux应用程序使用的主要函数库均存放于/ ...
- wxpython grid
构建Grid方法,效果如下: 其它构建grid方法和grid的使用见:还可以见下载资源中的wxpython教程第5章的 gridGeneric.py gridModel.py gridNoModel. ...
- java.lang.AbstractMethodError: Method com/mchange/v2/c3p0/impl/NewProxyPreparedStatement.isClosed()Z is abstract
二月 26, 2019 3:47:40 上午 org.apache.catalina.core.StandardWrapperValve invoke严重: Servlet.service() for ...
- 【Spring实战】—— 16 基于JDBC持久化的事务管理
前面讲解了基于JDBC驱动的Spring的持久化管理,本篇开始则着重介绍下与事务相关的操作. 通过本文你可以了解到: 1 Spring 事务管理的机制 2 基于JDBC持久化的事务管理 Spring的 ...