加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

C#实现队列(循环数组,线程安全)

(2010-11-21 20:39:40)
标签:

csharp

队列

循环数组

线程安全

分类: 技术总结
    /// <summary>
    /// 队列类(使用循环数组)(加上线程安全)
    /// </summary>
    /// <typeparam name="T">队列中元素的类型</typeparam>
    public class Queue<T>
    {
        /// <summary>
        /// 通知的状态机
        /// </summary>
        AutoResetEvent notice = new AutoResetEvent(true);
        /// <summary>
        /// 循环数组,初始大小为100
        /// </summary>
        T[] ary = new T[100];
        /// <summary>
        /// 队头
        /// </summary>
        int front = 0;
        /// <summary>
        /// 队尾
        /// </summary>
        int rear = 0;
        /// <summary>
        /// 队大小
        /// </summary>
        int size = 0;
        /// <summary>
        /// 入队
        /// </summary>
        /// <param name="t">入队元素</param>
        public void Enqueue(T t)
        {
            Lock();
            //如果队列大小等于数组长度,那么数组大小加倍
            if (size == ary.Length)
            {
                DoubleSize();
            }
            ary[rear] = t;
            //队尾前移
            rear++;
            //这一句是循环数组的关键:
            //如果rear超过数组下标了,
            //那么将从头开始使用数组。
            rear %= ary.Length;
            //大小加一
            size++;
            UnLock();
        }
        /// <summary>
        /// 出队
        /// </summary>
        /// <returns>出队元素</returns>
        public T Dequeue()
        {
            Lock();
            //如果大小为零,那么队列已经空了
            if (size == 0)
            {
                UnLock();
                throw new Exception("队列已经空了");
            }
            T t = ary[front];
            //队头前移
            front++;
            //这一句是循环数组的关键:
            //如果front超过数组下标了,
            //那么将从头开始使用数组。
            front %= ary.Length;
            //大小减一
            size--;
            UnLock();
            return t;
        }
        /// <summary>
        /// 从队头提取一个元素(不删除)
        /// </summary>
        /// <returns></returns>
        public T Peek()
        {
            Lock();
            //如果大小为零,那么队列已经空了
            if (size == 0)
            {
                UnLock();
                throw new Exception("队列已经空了");
            }
            T t = ary[front];
            UnLock();
            return t;
        }
        /// <summary>
        /// 队大小
        /// </summary>
        public int Count
        {
            get
            {
                Lock();
                int result = size;
                UnLock();
                return result;
            }
        }
        /// <summary>
        /// 清除队中的元素
        /// </summary>
        public void Clear()
        {
            Lock();
            size = 0;
            front = 0;
            rear = 0;
            ary = new T[ary.Length];
            UnLock();
        }
        /// <summary>
        /// 数组大小加倍
        /// </summary>
        private void DoubleSize()
        {
            //临时数组
            T[] temp=new T[ary.Length];
            //将原始数组的内容拷贝到临时数组
            Array.Copy(ary, temp, ary.Length);
            //原始数组大小加倍
            ary = new T[ary.Length * 2];
            //将临时数组的内容拷贝到新数组中
            for (int i = 0; i < size; i++)
            {
                ary[i] = temp[front];
                front++;
                front %= temp.Length;
            }
            front = 0;
            rear = size ;
        }
        /// <summary>
        /// 锁定
        /// </summary>
        private void Lock()
        {
            notice.WaitOne();
        }
        /// <summary>
        /// 解锁
        /// </summary>
        private void UnLock()
        {
            notice.Set();
        }
    }

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有