打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【C#高级编程(集合2)】 C#高级编程之实现队列读写操作

     实现队列读写操作

概述:集合大家都不陌生,但是实际应用确实有时候让人无从下手。其比数组最大的好处就是针对多变的动态的元素降服之功能!妙哉,笔者通过《C#高级编程》集合章节发现集合也会“博大精深,变化多端”的。但是有不同于书本,那么大一本厚书,让人敬而远之,特别一些些一套套理论的东西更是头大。笔者准备从集合的列表,队列,栈,链表,有序表,字典,等分系列发布。尽可呢避免大篇理论(核心的还是要强调的)。然后笔者自己做一些小实例,通过自己总结描述设计思想,结合代码实现,加以重点强调语句。最后配上运行结果!尽可能达到初学者有所悟吧。

C#基础系列导航


  1. C#实现队列读写操作(一)
  2. 变化多端的列表(二)
  3. VS自动内存管理(垃圾回收集)(三)
  4. C#忽略基础知识点梳理(四)
  5. 什么是框架的接口(五)
  6. 程序集的加载与反射(六)
  7. CLR寄宿和应用程序域(七)
  8. 异常(八)

【队列】队列对元素操作是实现出队和入队的原则,又遵循先进先出准则:即先放进队列中的元素先取出来,这个好比咱们在学校或公司排队买饭,排在前面的先买到饭,先买到的先离开。诸如此类的例子很多了。而且队列操作在一些业务逻辑上很重要,就像文件管理操作也可以用队列实现,待会咱们再用实例演示并加以分析。还有一点就是你在队列放入一些元素,初始化会分配一个n个大小的空间,当空间不足时候,会自动增长,并且是上一次的两倍大小。假如第一次分配n,第二次就是2n,第三次就是4n...这个符合集合分配方式,故队列也是集合一种!

【实例演示】下面做一个文档管理来演示Queue<T>,一个线程文档添加队列,另一个线程读取队列。这里面涉及几个类:

Document类:对文档属性和构造方法定义

DocumentManager类:数据入队出队即文档管理

ProcessDocuments类:单独线程处理队列中的文档

【涉及演示思想】

      本实例想通过文档操作,在队列中写入读取数据,然后咱们借助线程堆文档处理,以及客户端如何调用.以前对队列只是理论方法,不会具体使用,线程这次也派生用场.一例子多用.在Document类通过定义文档题目和文档内容和一个带参构造函数,对文档类设置.在DocumentManager类中通过AddDocument方法中队列的Enqueue方法写进去数据,记得加锁,在GetDocument方法中加锁实现Dequeue方法读取.当然还有判断什么时候队列为空,通过IsDocmentAvailiable判断对中总是是否小于0来判断是否为空.最后在ProcessDocuments类中,要想从外部启动进程必须使用start方法,注意,使用前先实例一个进程.利用ProcessDocuments类来启动线程.不过,run来启动线程方法.直到队列中数据为空,跳出while循环,终止进程.

【几个队列常用方法】

Enqueue:队列一端添加元素

Dequeue:头部取数据和删除,数据取空抛出异常

Peek:头部取数据,不删除

Count:队列元素个数

TrimExcess:Dequeue或Peek取数据,但不会删除队列内存大小,通过此方法重新设置容量,从头部去除空元素。

Contains:确定队列是否包含某个元素

CopyTo:元素从队列复制一个已有的数组中

TpArray:包含队列中新数组

1 队列中属性和构造函数设置:文档题目,内容,含参构造函数

    /// <summary>    /// 队列中属性和构造函数设置    /// </summary>    public  class Document    {        public string title { get; set; }        public string content { get; set; }        public Document(string title, string content)        {            this.title = title;            this.content = content;        }    }

2 读取文档操作即文档管理:实例化队列,并对其进行入队,出队,判断为空方法操作

    /// <summary>    /// 读取文档操作即文档管理    /// </summary>    public class DocumentManager    {        private readonly Queue<Document> documentQueue=new Queue<Document>();        public void AddDocument(Document doc)        {            lock(this)            {                documentQueue.Enqueue(doc);            }        }        public Document GetDocument()        {            Document doc = null;            lock (this)            {                doc = documentQueue.Dequeue();            }            return doc;        }        public bool IsDoctumentAvailable        {            get { return documentQueue.Count > 0; }        }    }

3 单独线程处理队列中的文档:设置含对象参数的构造函数,run方法启动线程,start方法外部启动线程

    /// <summary>    /// 单独线程处理队列中的文档    /// </summary>    public class ProcessDocuments    {        private DocumentManager documentManager;        public ProcessDocuments(DocumentManager dm)        {            this.documentManager = dm;        }        public static void Start(DocumentManager dm)        {            new Thread(new ProcessDocuments(dm).Run).Start();        }        public void Run()        {            while (true)            {                if (documentManager.IsDoctumentAvailable)                {                    Document doc = documentManager.GetDocument();                    Console.WriteLine("线程 目录{0}", doc.title);                }                Thread.Sleep(new Random().Next(20));            }        }    }


4 客户端调用:实例化文档管理方法,启动线程,两个线程添加读取数据

        static void Main(string[] args)        {            DocumentManager dm = new DocumentManager();            ProcessDocuments.Start(dm);            for (int i = 0; i < 100; i++)            {                Document doc = new Document("题目:" + i.ToString(), "内容:");                dm.AddDocument(doc);                Console.WriteLine("添加 题目 {0}", doc.title);                Thread.Sleep(new Random().Next(20));            }            Console.ReadKey();        }


【运行结果】岑参不齐的显示数据,一个线程添加,一个线程读取的原因.添加线程添加一个资源后,会释放资源,读取线程会读取.但是他们不是交替的,而是无规律的读取方式

【疑问和总结】为什么读取两个线程?到底机制在何处?

分析一:ProcessDocuments类中start方法来启动线程,如下操作会正常运行的.

        public static void Start(DocumentManager dm)        {            new Thread(new ProcessDocuments(dm).Run).Start();        }

分析二:假如start方法中如下设置,先实例化,在启动线程,最后外部方法调用线程,结果如何?

       public static void Start(DocumentManager dm)        {            ProcessDocuments pd = new ProcessDocuments(dm);            pd.Run();            new Thread(pd).Start();          }

分析结果:分析一正常运行,分析二报错.因为start启动前需要实例化一个新线程.调用run方法.分析二传入的只是一个对象.

到此,关于队列操作已经结束.接下来会有集合3栈的实例分析和实例演示!由于时间关系,累一天也该休息了.各位晚安!!!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
c#中queue队列用法
.NET中栈和堆的比较 - c#开发园地 - 博客园
CSDN 文档中心:针对开发人员的WebLogic Server应用管理,第 1 部分----基本概念和配置工具
C#设计模式系列:单件模式(Singleton)
C#中的线程(二) 线程同步基础
C# 温故而知新: 线程篇(四)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服