在很多项目中,尤其是服务端,我们需要临时缓存一些数据,对于完整的我就不说了。主要的保持方法有:

1.大型数据库

2.缓存组件

3.文件(按照自己定义的格式存储)

4.一些缓存数据库(sqlte,h2,mongdb,redis等)

5.自定义的缓存方法。

这里我主要说说第5种方法,自定义类

首先我们定义一个泛型模板,用于存储真正的数据。

public class BaseBuffer<T>
    {

/// <summary>
        /// 真实数据对象
        /// </summary>
        public T Data { get; set; }

/// <summary>
        /// 使用的时间
        /// </summary>
        public DateTime DateTime { get; set; }

//缓存丢失清理数据
        public virtual void Dispose()
        {

}

/// <summary>
        /// 重置
        /// </summary>
        public virtual void Reset()
        {

}
    }

类似这样一个结构。

在存储时,我们需要一个类来管理,也就是缓存池的对象。

public class BufferPool<T>
    {
        /// <summary>
        /// 缓存结构
        /// </summary>
        protected Stack<BaseBuffer<T>> buffers = new Stack<BaseBuffer<T>>(100);
        private readonly object lock_obj = new object();
        private int useNum = 0;//当前缓存使用
        private volatile bool isRun = false;//已经启动运算
        private int[] record = null;//记录
        protected int waitTime = 20;//计算的分钟时间
        private int index = 0;//索引计算
        private int  maxNum = 0;//最近一段时间最大使用
        private int havNum = 0;//已经创建的缓存
        private int minWaitTime = 100;//
        private int maxBufferNum = int.MaxValue;
        
        public BufferPool()
        {
            record = new int[waitTime];

}

/// <summary>
        /// 设置运行的最大值
        /// </summary>
        public int MaxBufferSize { get { return maxBufferNum; } set { maxBufferNum = value; } }
        /// <summary>
        /// 初始化缓存对象
        /// </summary>
        /// <param name="initNum"></param>
        public void InitPool(int initNum = 10)
        {
            if (initNum > 0)
            {
                for (int i = 0; i < initNum; i++)
                {
                    buffers.Push(Create());
                }
            }
        }

/// <summary>
        /// 刷新
        /// </summary>
        private void  RefreshCount()
        {
            if(isRun)
            {
                return;
            }
            isRun = true;
            Task.Factory.StartNew(() =>
            {
                Thread.Sleep(60000);//1分钟
                //
                record[index] = useNum;
                index++;
                if(index%waitTime==0)
                {
                    //监测waitTime分钟内没有使用的
                    lock (lock_obj)
                    {
                        var bufs= buffers.ToArray();
                        buffers.Clear();
                        foreach(var buf in bufs)
                        {
                            if((DateTime.Now-buf.DateTime).TotalMinutes<waitTime)
                            {
                                buffers.Push(buf);
                            }

else
                            {
                                buf.Dispose();
                            }
                        }
                        //
                        int sum = 0;
                        int avg = 0;
                        for(int i=0;i<record.Length;i++)
                        {
                            sum += record[i];
                        }
                        //计算时间内的平均值
                        avg = sum / record.Length;
                        //如果当前使用小于平均值,则最多只保留平均值个数
                        //说明当前使用可能在下降
                        if(useNum<avg&&buffers.Count>avg)
                        {
                            int num = buffers.Count - avg;
                            for (int i=0;i<num;i++)
                            {
                                var buf=  buffers.Pop();
                                buf.Dispose();//不使用时释放
                            }
                        }
                       if(useNum>avg&&useNum>maxNum&&buffers.Count> maxNum)
                        {
                            //当前使用大于平均值,并且大于最近的最大值,说明再继续增加可能
                            //那就以最大缓存值为准
                            int num = buffers.Count - avg;
                            for (int i = 0; i < num; i++)
                            {
                                var buf = buffers.Pop();
                                buf.Dispose();//不使用时释放
                            }
                        }

}
                }
                isRun = false;
            });
        }
        /// <summary>
        /// 创建缓存对象
        /// </summary>
        /// <returns></returns>
        public virtual BaseBuffer<T> Create()
        {
            Interlocked.Increment(ref havNum);
            return new BaseBuffer<T>();
        }

/// <summary>
        /// 获取缓存对象
        /// </summary>
        /// <returns></returns>
        public BaseBuffer<T> GetBuffer()
        {
            lock (lock_obj)
            {
                try
                {
                    if (useNum < havNum)
                    {
                        //正在使用的小于已经创建的缓存
                        BaseBuffer<T> cache = buffers.Pop();
                        cache.DateTime = DateTime.Now;
                        useNum++;
                        this.RefreshCount();
                        return cache;
                    }
                    else if(havNum<maxBufferNum)
                    {
                        return Create();
                    }
                    else
                    {
                        return null;
                    }
                }
                catch
                {
                    return Create();
                }
            }
        }

/// <summary>
        /// 超时获取数据
        /// </summary>
        /// <param name="waitTime">等待时间(毫秒)</param>
        /// <param name="buffer">获取的buffer对象</param>
        /// <returns>获取成功</returns>
         public bool TryGetBuffer(int waitTime=0, out  BaseBuffer<T>  buffer)
        {
            buffer = null;
            if(waitTime<1)
            {
                if((buffer = GetBuffer())==null)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                int sleepTime = 0;
                int sum = 0;
                if (waitTime < minWaitTime)
                {
                    sleepTime = waitTime;
                }
                else
                {
                    sleepTime = 100;
                }
                while ((buffer = GetBuffer()) == null)
                {
                    Thread.Sleep(sleepTime);
                    sum += sleepTime;
                    if (sum > waitTime)
                    {
                        break;
                    }
                }
                if(buffer==null)
                {
                    //最后再获取一次
                    buffer = GetBuffer();
                    if(buffer==null)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return true;
                }
            }
        }

/// <summary>
        /// 获取一组缓存
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public virtual List<BaseBuffer<T>> GetCacheBuffers(int num)
        {
            List<BaseBuffer<T>> list = new List<BaseBuffer<T>>(num);
            for(int i=0;i<num;i++)
            {
                list.Add(GetBuffer());
            }
            return list;
        }
        /// <summary>
        /// 缓存释放
        /// </summary>
        /// <param name="client"></param>
        public void Free(BaseBuffer<T> client)
        {
            lock (lock_obj)
            {
                useNum--;
                buffers.Push(client);
            }
        }
    }

一看就懂,不懂就完全弄到你的VS2017上面看看。

其实主要是回收缓存对象。获取对象,获取时提供了2个方法,直接获取以及有时间等待的。

刷新统计方法主要是用来动态平衡的。以20分钟为粒度。计算平均值,动态释放一些不需要的。

为什么使用的是Stack?

因为它是先进后出,这样如果有buffer一段时间没有使用,则它一直在尾部,例如:有100个buffer,一段时间只有了80个,另外20个就一直不会使用,这样在启动线程监测buffer时,就知道你有20个一直没有用,于是这20个算超时没有使用的,直接释放。

另外一类自定义缓存实现,推荐博文,我也集成到了我的项目模板中。

我自己的实现已经传到git,地址与前面博文提供的地址一样,项目名称是CacheBuffer

https://www.cnblogs.com/ylsforever/p/6511000.html

https://blog.csdn.net/niss/article/details/8764738

转载于:https://www.cnblogs.com/jinyu20180311/p/10312360.html

c# 一种缓存模板相关推荐

  1. Django中提供的6种缓存方式

    由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用: 缓存,缓存将一个某个views的返回值保存至内存或者memcache中, ...

  2. 微软BI 之SSIS 系列 - Lookup 组件的使用与它的几种缓存模式 - Full Cache, Partial Cache, NO Cache...

    开篇介绍 先简单的演示一下使用 Lookup 组件实现一个简单示例 - 从数据源表 A 中导出数据到目标数据表 B,如果 A 数据在 B 中不存在就插入新数据到B,如果存在就更新B 和 A 表数据保持 ...

  3. 谈表达式树的缓存(7):五种缓存方式的总体分析及改进方案

    终于到了这个系列的最后一篇文章了,这个系列的文章本是许多话题的基础,却拖了那么长时间还没有完结.这篇文章主要讨论五种缓存方式各自的优劣,以及他们的性能关键在什么地方,如果要进行改进又有什么可选方案.在 ...

  4. pyqt漂亮gui界面模板_一种基于模板的C代码自动生成方法

    在做C代码项目的时候,我们期望做到代码的高复用,高复用意味着代码的高配置性,即通过简单的配置修改达到复用代码的目的.如果代码高复用,支持灵活的配置,那么完全可以在上边做一个更简单的配置工具,用来修改代 ...

  5. [vue-cli]vue-cli提供了的哪几种脚手架模板?

    [vue-vuex]vue-cli提供了的哪几种脚手架模板? vue-cli2.x 好像有个simple和完整版的 vue-cli3.x 提供了自定义装箱配置 可以选装TypeScriptPWAlin ...

  6. 【Elasticsearch】Elasticsearch 缓存深度剖析:一次提高一种缓存的查询速度

    1.概述 转载:Elasticsearch 缓存深度剖析:一次提高一种缓存的查询速度 缓存是加快数据检索速度的王道.因此,如果您有兴趣了解 Elasticsearch 如何利用各种缓存来确保您尽可能快 ...

  7. 浏览器端的九种缓存机制介绍

    浏览器缓存是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用可以避免重复的网络请求和浏览器快速地读取本地数据,整体上加速网页展示给用户.浏览器端缓存的机制种类较多,总体归纳为九 ...

  8. 谈表达式树的缓存(6):五种缓存方式的性能比较

    开始还债,因为还有至少两个可写的重要话题依赖在这个系列上,不解决就难以前进. 目前我们已经涉及了五种不同的缓存实现,它们分别是: SimpleKeyCache:构造字符串作为Key,使用字典作为存储. ...

  9. 如果不知道这4种缓存模式,敢说懂缓存吗?

    概述 在系统架构中,缓存可谓提供系统性能的最简单方法之一,稍微有点开发经验的同学必然会与缓存打过交道,最起码也实践过. 如果使用得当,缓存可以减少响应时间.减少数据库负载以及节省成本.但如果缓存使用不 ...

最新文章

  1. PNAS:人工构建玉米极简微生物组
  2. Android实践 -- 监听应用程序的安装、卸载
  3. 有助于改善性能的技巧(1)
  4. Android 自定义View的使用纪要!!!
  5. [POJ-3237] [Problem E]
  6. VC的包含文件和引用文件是不一样的~
  7. 输出商品列表 用户输入序号 显示用户选中的商品
  8. POJ 3237 Tree (树链剖分)
  9. 四、从Excel开始,学习Excel的快捷键
  10. 机器人摘果子看图写话_看图写话——聪明的小白兔
  11. 小汤学编程之JavaScript学习day02——运算符、流程控制与循环、函数
  12. Ogre1.7的地形、天空与雾
  13. python与乐高ev3结合_EV3结合PYTHON主题编程之驱动车
  14. XP系统优化简单实用技法
  15. 离线语音风扇设计应用案例
  16. React表格内容换行并用省略号显示
  17. html文档在word打开是乱码怎么解决,word打开是乱码的解决方法
  18. Python面向对象版学员管理系统
  19. 2022年家用投影仪推荐 当贝F5和坚果J10S哪款画质更好?
  20. 安搭Share:熬夜,对于身体健康的损坏程度,不亚于过度劳累

热门文章

  1. 输入三科成绩 C语言,C语言题,对我的程序找错修改。输入10个学生学号,三科成绩,求总成绩和平均分,并按成绩由高到低输出...
  2. php 查询cpu使用率,php获取CPU使用情况的代码
  3. PDE8 wave equation: derivation
  4. fprintf,input和disp函数
  5. pytorch图像预处理
  6. python函数里面可以修改一些数据类型
  7. python tab键自动补全_设置python中TAB键自动补全方法
  8. 如何选择神经网络的超参数
  9. oracle 查虚拟路径,Oracle 11g RMAN虚拟私有目录
  10. 学生HTML5今后的打算,今后我打算小学生日记