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

队列】队列对元素操作是实现出队和入队的原则,又遵循先进先出准则:即先放进队列中的元素先取出来,这个好比咱们在学校或公司排队买饭,排在前面的先买到饭,先买到的先离开。诸如此类的例子很多了。而且队列操作在一些业务逻辑上很重要,就像文件管理操作也可以用队列实现,待会咱们再用实例演示并加以分析。还有一点就是你在队列放入一些元素,初始化会分配一个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:包含队列中新数组

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

/// <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;
        }
    }


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

/// <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; }
        }
    }




单独线程处理队列中的文档:设置含对象参数的构造函数,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));
            }
        }
    }


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

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方法.分析二传入的只是一个对象.

到此,关于队列操作已经结束.

时间: 2025-01-01 16:27:52

【C#高级编程(集合2)】 C#高级编程之实现队列读写操作的相关文章

iOS开发那些事-iOS网络编程同步GET方法请求编程

iOS SDK为HTTP请求提供了同步和异步请求两种不同的API,而且可以使用GET或POST等请求方法.我们先了解其中最为简单的同步GET方法请求. 为了学习这些API的使用MyNotes"备忘录"应用实例,数据来源于服务器端,而不是本地的Notes.xml(或Notes.json)文件. 首先实现查询业务,查询业务请求可以在主视图控制器MasterViewController类中实现,其中MasterViewController.h代码如下: #import <UIKit/U

5天玩转C#并行和多线程编程 —— 第五天 多线程编程大总结

5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 -- 第一天 认识Parallel 5天玩转C#并行和多线程编程 -- 第二天 并行集合和PLinq 5天玩转C#并行和多线程编程 -- 第三天 认识和使用Task 5天玩转C#并行和多线程编程 -- 第四天 Task进阶 5天玩转C#并行和多线程编程 -- 第五天 多线程编程大总结    一.多线程带来的问题 1.死锁问题  前面我们学习了Task的使用方法,其中Task的等待机制让我们瞬间爱上了它,但是如果我们在调用Ta

Java编程那些事儿9——网络编程基础

对于初学者,或者没有接触过网络编程的程序员,会觉得网络编程涉及的知识很高深,很难,其实这是一种误解,当你的语法熟悉以后,其实基本的网络编程现在已经被实现的异常简单了. 1.4.1 网络编程是什么? 网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算机.数据传递本身没有多大的难度,不就是把一个设备中的数据发送给两外一个设备,然后接受另外一个设备反馈的数据. 现在的网络编程基本上都是基于请求/响应方式的,也就是一个设备发送请求数据给另外一个,然后接收另一个设备的反馈. 在网

Java编程那些事儿105——网络编程技术4

13.2.4 UDP编程 网络通讯的方式除了TCP方式以外,还有一种实现的方式就是UDP方式.UDP(User Datagram Protocol),中文意思是用户数据报协议,方式类似于发短信息,是一种物美价廉的通讯方式,使用该种方式无需建立专用的虚拟连接,由于无需建立专用的连接,所以对于服务器的压力要比TCP小很多,所以也是一种常见的网络编程方式.但是使用该种方式最大的不足是传输不可靠,当然也不是说经常丢失,就像大家发短信息一样,理论上存在收不到的可能,这种可能性可能是1%,反正比较小,但是由

javaee-当String的对象,从a编程ab的时候,底层jvm会执行哪些操作?

问题描述 当String的对象,从a编程ab的时候,底层jvm会执行哪些操作? 我觉这个问题会设计到很多的知识点 public static void f3(){ String str = "a"; str+="b"; } 例如线程,栈,堆 各位们可以说下自己的理解吗? 解决方案 先创建一个str指向存储a的内存,相加的时候产生b的内存,加完产生存储ab的内存并且str指向存储ab的内存,a b短时间还再占用内存随后被回收 解决方案二: 字符串的操作相对特殊,每次操

树-一道编程题,用c++编程,求助

问题描述 一道编程题,用c++编程,求助 给定一颗无根树,假设它有n个节点,节点编号从1到n,求任意两点之间的距离之和,也就是求任意一点到其它点的距离之和,边长都为1.要求时间复杂度为O(n) 解决方案 先做一遍DFS求出所有节点到根节点的距离之和,然后可以发现,如果知道到一个点的距离之和,可以用O(1)求出所有节点到它相邻点的距离之和 解决方案二: /* ***********************************************Author :xdloveCreated T

求助 编程 就业 能力-编程到底难不难?编程这一行业一定要智力很高么?

问题描述 编程到底难不难?编程这一行业一定要智力很高么? 我是一个"貌似"很热爱编程的人,我想把这个编程作为我的职业.我现在学的专业是临床医学,我觉得这个很烂,没兴趣,很抵触.我唯一能走的可能就是软件.但是,我不知道我是不是真正的能在这个领域做出什么成就来,不需要很高的成绩. 或者说,我不知道我到底适不适合干编程这行?这行业,将来会面临什么样的问题? 所以,我问问,这行业最难得是什么,不仅仅是知识方面,还有将来就业方面?或者,怎么才能知道我是不是叶公好龙,是不是真真适合这个行业?有没有

VB编程 及EXCEL 的VBA编程,用什么把一段代码括起来啊(就是用什么东西来实现C语言中的{}功能啊)?

问题描述 VB编程及EXCEL的VBA编程,用什么把一段代码括起来啊(就是用什么东西来实现C语言中的{}功能啊)? 解决方案 解决方案二:不是有begin和end吗解决方案三:region?C的{}有很多啊,只能你VB书都没看过if...endif-------------if{}for...endfor---------for{}解决方案四:for..next.............我草解决方案五:学c的时候用按键精灵的时候我也愣了一阵子...很多是用end,if之后用endif,while

c语言-请教一个C编程 打印输出图像的算法编程

问题描述 请教一个C编程 打印输出图像的算法编程 解决方案 大概就是这样,建立笛卡尔坐标系. 用point()函数里的嵌套for循环来输出每一个字符,然后把代表坐标的i和j传递给getChar()函数通过坐标来决定输出的是什么字符. 解决方案二: char getChar(int x,int y,int n) { if(x<0) x=-x; if(y<0) y=-y; if(x>y) { if(n-x<=2) return 'x'+n-x; else return '0'+n-x-