shaneplot

简易的对象缓存管理器(C#实现)

小菜入行快两年了,记录一下自己工作过程中属于自己的东西.同时也希望各位大虾指导给给予宝贵意见,如果能对各位同行朋友有所启发或帮助,实是荣幸之致。

这里先放一个对象缓存器,一般我们有些对象会经常使用,但是每次使用时都要创建它,如果这个创建过程比较复杂(比如通过一个复杂算法创建,比如需要查找数据库的实体类等等)的话,那么多次使用时就会消耗CPU了,所以我们打算把这些对象保存在内存里,再给每个对象一个动态的时间段生存标志,那么它在这个时间段内再次被调用就不再需要重新创建拉,而是直接从内存里读出来,下面放代码,缓存器是线程安全的,存入对象时不需要再加锁。

 

代码

 

   /// <summary>
    /// 读取标志类
    /// </summary>
    public class ReadFlag
    {
        private int readCount;
        /// <summary>
        /// 读取次数
        /// </summary>
        public int ReadCount
        {
            get { return readCount; }
            set { readCount = value; }
        }

        private DateTime lastReadTime;
        /// <summary>
        /// 最后读取时间
        /// </summary>
        public DateTime LastReadTime
        {
            get { return lastReadTime; }
            set { lastReadTime = value; }
        }

        public ReadFlag(DateTime birthTime)
        {
            this.readCount = 0;
            this.lastReadTime = birthTime;
        }
    }

    public class ElementBuffer<TKey, Tobject>
    {
        public Dictionary<TKey, ReadFlag> ReadFlagBuffer = new Dictionary<TKey, ReadFlag>();
        public Dictionary<TKey, Tobject> Buffer = new Dictionary<TKey, Tobject>();
    }

    /// <summary>
    /// 对象缓存器
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="Tobject"></typeparam>
    public class ObjectCache<TKey, Tobject>
    {
        private int objectCount = 100;
        /// <summary>
        /// 缓存内最大允许的Object数量
        /// </summary>
        public int ObjectCount
        {
            get { return objectCount; }
            set { objectCount = value; }
        }

        private int loseTime = 100;
        /// <summary>
        /// 失效时间,秒为单位
        /// </summary>
        public int LoseTime
        {
            get { return loseTime; }
            set { loseTime = value; }
        }

        private ElementBuffer<TKey, Tobject> buffer = new ElementBuffer<TKey, Tobject>();

        public object this[TKey key]
        {
            get
            {
                Tobject ret;
                if (this.buffer.ReadFlagBuffer.ContainsKey(key) && this.buffer.Buffer.TryGetValue(key, out ret))
                {
                    lock (this.buffer)
                    {
                        this.buffer.ReadFlagBuffer[key].ReadCount++;
                        this.buffer.ReadFlagBuffer[key].LastReadTime = DateTime.Now;
                    }
                    return ret;
                }
                else
                {
                    return null;
                }
            }
            set
            {
                Tobject ret;
                if (this.buffer.ReadFlagBuffer.ContainsKey(key) && this.buffer.Buffer.TryGetValue(key, out ret))
                {
                    ret = (Tobject)value;
                }
                else
                {
                    lock (this.buffer)
                    {
                        if (this.buffer.ReadFlagBuffer.Count > this.objectCount)
                        {
                            TKey removeKey;
                            TKey[] array = new TKey[this.buffer.ReadFlagBuffer.Keys.Count];
                            this.buffer.ReadFlagBuffer.Keys.CopyTo(array, 0);
                            removeKey = array[0];
                            foreach (TKey tkey in this.buffer.ReadFlagBuffer.Keys)
                            {
                                if (this.buffer.ReadFlagBuffer[tkey].LastReadTime.AddSeconds(this.LoseTime).CompareTo(DateTime.Now) < 0)
                                {
                                    removeKey = tkey;
                                    break;
                                }
                                if (this.buffer.ReadFlagBuffer[tkey].ReadCount < this.buffer.ReadFlagBuffer[removeKey].ReadCount)
                                {
                                    removeKey = tkey;
                                }
                            }
                            this.Remove(removeKey);
                        }
                        else
                        {
                            ReadFlag readFlag = new ReadFlag(DateTime.Now);
                            this.buffer.ReadFlagBuffer.Add(key, readFlag);
                            this.buffer.Buffer.Add(key, (Tobject)value);
                        }
                    }
                }
            }
        }

        private void Remove(TKey key)
        {
            lock (this.buffer)
            {
                this.buffer.Buffer.Remove(key);
                this.buffer.ReadFlagBuffer.Remove(key);
            }
        }
    }

 

 

 

 上面ReadFlag是一个标志类,对象管理器里存入的每个对象都会获得对应的一个标志对象来描述它,标志对象有两个属性值,分别是对应对象的被读取次数,还有最后一次被访问的时间,构造函数的参数是对象生成时间。其中最后一次访问时间是管理器运行时根据最后读取时间,选择距离现在最远的对象进行删除,控制对象在内存中的数量。

ObjectCache就是缓存管理器了,它的使用很简单。

static ObjectCache<string,T> Buffer=new ObjectCache<string,T>();先创建缓存器,这里key值用了string类型,推荐用这样的,或者int等简单类型最好。

那么我们就可以使用根据string类型的参数key来获取我们存进去的对象了,就是Buffer[key] as T;

同样我们可以把对象object(注意必须是T类型对象哦)存进Buffer了,Buffer[key] = object;

缓存管理器有2个属性可以自定义,有默认值,分别是最大对象数量,即管理器允许存的对象个数,另一个是失效时间,就是当对象数量达到管理器允许存的最大值时,就会把超过失效时间的对象替换掉。

 

 

posted on 2009-12-15 15:10  shanechow  阅读(1496)  评论(6编辑  收藏  举报

导航