LRU最近最少使用缓存集合

       编码中涉及到资源管理就会经常使用到最近最少使用淘汰原理(LRU),比如说最近打开的文章列表管理、或者游戏中动态加载地图、音乐一样。使用LRU可以提高效率。本文实现了一个完整功能的LRU集合,可用于各种诸如此类需要缓存机制的地方。

    /// <summary>
    /// 使用最近最少算法进行淘汰的缓存集合,用于缓存数据.
    /// 提供了多线程安全访问功能
    /// </summary>
    /// <remarks>    
    /// 1、调用方在每使用一个数据之后,调用UpdateRecentlyUsed函数将该数据
    /// 置为最近访问。函数会将该条目的读取权值设为最大值。
    /// 2、在使用Add或者Insert添加条目时,如果缓存数目已达到设定的CacheSize值,
    /// 则会根据删除掉缓存列表中读取权值最小的条目。再进行添加
    /// </remarks>
    public class LRUCacheList<T> : IList<T>
    {
        #region Property
        /// <summary>
        /// 实际存放缓存条目的列表
        /// </summary>
        private List<T> m_listData;

        /// <summary>
        /// 存放与m_listData依次对应条目的最近读取记录
        /// </summary>
        private List<uint> m_listReadWeight;

        /// <summary>
        /// 当前最大的读取记录权值,用来计算下一个读取值
        /// </summary>
        private uint m_iMaxWeight;

        /// <summary>
        /// 一个无符号整数的最大值
        /// </summary>
        private const uint c_MaxWeight = 0xffffffff;

        private Object m_lockObj = new object();

        /// <summary>
        /// 读取和设置缓存大小,指定最多缓存的对象数目
        /// </summary>
        public int CacheSize { get; set; }
        #endregion

        #region Method

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cacheSize">缓存数目</param>
        public LRUCacheList(int cacheSize)
        {
            m_listData = new List<T>(cacheSize);
            m_listReadWeight = new List<uint>(cacheSize);
            CacheSize = cacheSize;
        }


        /// <summary>
        /// 移除掉最近最少使用的条目
        /// </summary>
        protected void RemoveLeastRecentlyUsed()
        {
            lock (m_lockObj)
            {
                uint min = c_MaxWeight;
                int minIndex = -1;

                for (int i = 0; i < m_listReadWeight.Count; i++)
                {
                    if (m_listReadWeight[i] < min)
                    {
                        min = m_listReadWeight[i];
                        minIndex = i;
                    }

                }

                if (minIndex != -1)
                {
                    m_listReadWeight.RemoveAt(minIndex);
                    m_listData.RemoveAt(minIndex);
                }
            }

        }


        /// <summary>
        /// 更新指定位置的权重值为最近访问
        /// </summary>
        /// <param name="index"></param>
        public void UpdateRecentlyUsed(T item)
        {
            lock (m_lockObj)
            {
                int index = m_listData.IndexOf(item);
                if (index != -1)
                    UpdateRecentlyUsed(index);
            }
        }

        /// <summary>
        /// 更新指定位置的权重值为最近访问
        /// </summary>
        /// <param name="index"></param>
        public void UpdateRecentlyUsed(int index)
        {
            m_listReadWeight[index] = NextMaxWeight();
        }

        /// <summary>
        /// 清除掉所有缓存的内容
        /// </summary>
        public void Clear()
        {
            lock (m_lockObj)
            {
                if (m_listData != null)
                    m_listData.Clear();

                if (m_listReadWeight != null)
                    m_listReadWeight.Clear();

                m_iMaxWeight = 0;
            }
        }

        /// <summary>
        /// 获取并设置下一个最大的权重值
        /// </summary>
        /// <returns></returns>
        public uint NextMaxWeight()
        {
            lock (m_lockObj)
            {
                //到达最大值重置
                if (m_iMaxWeight == c_MaxWeight - 1)
                {
                    m_iMaxWeight = 0;
                    for (int i = 0; i < m_listReadWeight.Count; i++)
                    {
                        m_listReadWeight[i] = 0;
                    }
                }
                m_iMaxWeight++;
                return m_iMaxWeight;
            }
        }

        /// <summary>
        /// 添加一个条目并设置为最近访问
        /// </summary>
        /// <param name="item"></param>
        public void AddRecently(T item)
        {
            lock (m_lockObj)
            {
                while (CacheSize > 0 && m_listData.Count >= CacheSize)
                    RemoveLeastRecentlyUsed();

                m_listData.Add(item);
                m_listReadWeight.Add(NextMaxWeight());
            }

        }

        /// <summary>
        /// 插入一个条目并设置为最近访问
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        public void InsertRecently(int index, T item)
        {
            lock (m_lockObj)
            {
                while (CacheSize > 0 && m_listData.Count >= CacheSize)
                    RemoveLeastRecentlyUsed();

                m_listData.Insert(index, item);
                m_listReadWeight.Insert(index, NextMaxWeight());
            }
        }

        #endregion



        #region 实现IList<T> 接口

        public void Add(T item)
        {
            lock (m_lockObj)
            {
                while (CacheSize > 0 && m_listData.Count >= CacheSize)
                    RemoveLeastRecentlyUsed();
                m_listData.Add(item);
                m_listReadWeight.Add(0);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>

        public int IndexOf(T item)
        {
            return m_listData.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            lock (m_lockObj)
            {
                while (CacheSize > 0 && m_listData.Count >= CacheSize)
                    RemoveLeastRecentlyUsed();

                m_listData.Insert(index, item);
                m_listReadWeight.Insert(index, 0);
            }
        }

        public void RemoveAt(int index)
        {
            lock (m_lockObj)
            {
                m_listData.RemoveAt(index);
                m_listReadWeight.RemoveAt(index);
            }
        }

        public T this[int index]
        {
            get
            {
                return m_listData[index];
            }
            set
            {
                m_listData[index] = value;
            }
        }


        public bool Contains(T item)
        {
            return m_listData.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            m_listData.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return m_listData.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(T item)
        {
            lock (m_lockObj)
            {
                int index = m_listData.IndexOf(item);
                if (index != -1)
                    m_listReadWeight.RemoveAt(index);
                return m_listData.Remove(item);
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return m_listData.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return m_listData.GetEnumerator();
        }
        #endregion

    }

  

posted @ 2012-12-02 20:09  Kecp  阅读(428)  评论(0编辑  收藏  举报