zoukankan      html  css  js  c++  java
  • c# 一种缓存模板

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

    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

  • 相关阅读:
    hdu 5524 Subtrees 递推
    一些数论函数
    hdu 5480 Conturbatio (前缀和)
    hdu 5479 Scaena Felix (好坑的简单题)
    hdu 5465 Clarke and puzzle(树状数组 或 前缀和 + Nim游戏)
    uva 10534 Wavio Sequence(LIS)
    MFC简单绘制安卓机器人
    解决kubuntu(KDE4.8.5桌面环境)找不到中文语言包
    Windows系统完全退出VMware方法
    【VC6.0】getline需要输入2次回车才会结束的BUG修复方法
  • 原文地址:https://www.cnblogs.com/jinyu20180311/p/10312360.html
Copyright © 2011-2022 走看看