环形堆栈

查看Queue的源码发现其实队列里面维护的是一个数组,而且这个数组是一直增加的,队列push一个就放到数组的最后,pop的时候就把数组最前面取出然后置为Null,这样必然导致在大量的pop和push操作后
会在数组前面产生大量的值为Null的数组元素。这个时候就可以用到 TrimToSize 方法进行从新分配数组,把多余的Null去掉。

现在可以实现一个定长的环形堆栈RingStack,可以对循环利用。

  /// <summary>
    /// 环形堆栈类,长度固定,顶与底相接形成一个圆环,需自定义覆盖时丢弃对象的处理方法
    /// </summary>
    /// <typeparam name="T">环形堆栈中对象的类型</typeparam>
    /// <remarks>属于一个固定大小的堆栈式缓存,当增长速度过快时自动覆盖最先压入的对象</remarks>
    public sealed class RingStack<T>
    {
        /// <summary>
        /// 堆栈的容量
        /// </summary>
        public readonly int Capacity;

        /// <summary>
        /// 堆栈的数据集
        /// </summary>
        private T[] _Items;

        /// <summary>
        /// 堆栈顶部的指针
        /// </summary>
        private int _TopIndex;

        /// <summary>
        /// 堆栈底部的指针
        /// </summary>
        private int _BottomIndex;

        /// <summary>
        /// 对象的数量
        /// </summary>
        private int _Count;

        /// <summary>
        /// 获取堆栈中对象的数量
        /// </summary>
        /// <remarks>此属性的读取是内部锁定的,因此多线程操作是安全的</remarks>
        public int Count
        {
            get
            {
                lock (this)
                {
                    return _Count;
                }
            }
        }

        /// <summary>
        /// 覆盖时丢弃对象的处理方法
        /// </summary>
        public Action<T> Drop;

        /// <summary>
        /// 初始化环形堆栈的新实例
        /// </summary>
        /// <param name="capacity">堆栈的容量</param>
        public RingStack(int capacity)
        {
            Capacity = capacity;
            _Items = new T[Capacity];
            _TopIndex = _BottomIndex = 0;
            _Count = 0;
        }

        /// <summary>
        /// 从堆栈中弹出一个对象
        /// </summary>
        /// <param name="item">弹出的对象</param>
        /// <returns>返回是否成功弹出对象,true表示弹出对象成功,false表示弹出对象失败</returns>
        /// <remarks>此操作是内部锁定的,因此多线程操作是安全的</remarks>
        public bool Pop(ref T item)
        {
            lock (this)
            {
                if (_TopIndex == _BottomIndex)
                {
                    return false;
                }
                item = _Items[_TopIndex];
                if ((--_TopIndex) == -1)
                {
                    _TopIndex = Capacity - 1;
                }
                --_Count;
                return true;
            }
        }

        /// <summary>
        /// 将指定的对象压入堆栈
        /// </summary>
        /// <param name="item">需要压入的对象</param>
        /// <remarks>此操作是内部锁定的,因此多线程操作是安全的</remarks>
        public void Push(T item)
        {
            Console.WriteLine(string.Format("top:{0},bott:{1}", _TopIndex, _BottomIndex));
            lock (this)
            {
                if ((++_TopIndex) == Capacity)
                {
                    _TopIndex = 0;
                }
                if (_TopIndex == _BottomIndex)
                {
                    if ((++_BottomIndex) == Capacity)
                    {
                        _BottomIndex = 0;
                    }
                    if (Drop != null)
                    {
                        Drop(_Items[_BottomIndex]);
                    }
                    --_Count;
                }

                _Items[_TopIndex] = item;
                //_TopIndex++;
                ++_Count;

                
            }
        }

        /// <summary>
        /// 清除堆栈中的所有对象
        /// </summary>
        /// <remarks>此操作是内部锁定的,因此多线程操作是安全的</remarks>
        public void Clear()
        {
            lock (this)
            {
                T t = default(T);
                while (_Count > 0)
                {
                    Pop(ref t);
                    if (Drop != null)
                    {
                        Drop(t);
                    }
                }
            }
        }
    }


原文地址:https://www.cnblogs.com/yangleiWPF/p/4565412.html