使用C#的泛型队列Queue实现生产消费模式
本篇体验使用C#的泛型队列Queue<T>实现生产消费模式。
如果把生产消费想像成自动流水生产线的话,生产就是流水线的物料,消费就是某种设备对物料进行加工的行为,流水线就是队列。
现在,要写一个体现生产消费模式的泛型帮助类,比如叫ProducerConsumer<T>。
该类肯定会维护一个有关生产、物料的Queue<T>类型的字段,还存在一个有关消费、Action<T>类型的字段。
在ProducerConsumer类的构造函数中,为Action<T>类型的字段赋值,并开启后台有关消费的线程。
ProducerConsumer类肯定存在一个进队列的方法,并且要保证在多线程情况下,同一时间只有一个生产或物料进入队列。
ProducerConsumer类还存在一个有关消费的方法,并且保证在多线程情况下,同一时间只有一个生产或物料出列,并消费它。
另外,在生产或物料在出队列的时候,可能会出现队列中暂时没有生产或物料的情况,这时候我们希望线程阻塞一下,这需要通过AutoResetEvent实现。AutoResetEvent的大致原理是:当生产或物料进入队列的时候需要告诉AutoResetEvent一下,当队列中暂时没有生产或物料的时候,也需要告诉AutoResetEvent,让它来阻塞线程。
//有关生产消费的泛型类public class ProducerConsumer<T>{//用来存储生产者的队列private readonly Queue<T> queue = new Queue<T>();//锁private readonly object queueLocker = new object();//消费行为private readonly Action<T> consumerAction;//出列的时候需要检查队列中是否有元素,如果没有,需要阻塞private readonly AutoResetEvent queueWaitHandle = new AutoResetEvent(false);public ProducerConsumer(Action<T> consumerAction){if (consumerAction == null){throw new ArgumentNullException("consumerAction");}this.consumerAction = consumerAction;//后台开启一个线程开始消费生产者new Thread(this.ConsumeItems){IsBackground = true}.Start();}//进列public void Enqueue(T item){//确保同一时间只有一个生产者进列lock (queueLocker){queue.Enqueue(item);//每次进列都要设置AutoResetEvent事件this.queueWaitHandle.Set();}}//消费动作private void ConsumeItems(){while (true){T nextItem = default(T);//标志,确认队列中的生产者是否存在bool doesItemExist;//确保同一时间只有一个生产者出列lock (this.queueLocker){//先确认队列中的生产者是否存在doesItemExist = this.queue.Count > 0;if (doesItemExist){nextItem = this.queue.Dequeue();}}//如果生产者存在,才消费生产者if (doesItemExist){this.consumerAction(nextItem);}else//否则的话,再等等下一个队列中的生产者{this.queueWaitHandle.WaitOne();}}}}
客户端,针对多线程情形。
class Program{static void Main(string[] args){//实例化一个int类型的生产消费实例var producerConsumer = new ProducerConsumer<int>(i => Console.WriteLine("正在消费" + i));Random random = new Random();//开启进队列线程var t1 = new Thread(() =>{for (int i = 0; i < 100; i++){producerConsumer.Enqueue(i);Thread.Sleep(random.Next(0,5));}});var t2 = new Thread(() =>{for (int i = 0; i > -100; i--){producerConsumer.Enqueue(i);Thread.Sleep(random.Next(0, 5));}});t1.Start();t2.Start();t1.Join();t2.Join();Thread.Sleep(50);Console.ReadKey();}}
使用C#的泛型队列Queue实现生产消费模式的更多相关文章
- C# 队列Queue,ConcurrentQueue,BlockingCollection 并发控制lock,Monitor,信号量Semaphore
什么是队列? 队列Queues,是一种遵循先进先出的原则的集合,在.netCore中微软给我们提供了很多个类,就目前本人所知的有三种,分别是标题提到的:Queue.ConcurrentQueue.Bl ...
- 消息队列Queue大全
消息队列Queue大全 (http://queues.io/) 作业队列,消息队列和其他队列.几乎所有你能想到的都在这. 关于 那里有很多排队系统.他们每个人都不同,是为解决某些问题而创建的.这个页面 ...
- 使用队列queue实现一个简单的生产者消费者模型
一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...
- Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...
- 线程队列queue
队列queue 队列用于线程之间安全的信息交换 队列和列表的区别:队列里的信息get()后就没了,而列表获取数据则是copy,原列表里的值还在 使用前先实例化队列 q = queue.Queue(ma ...
- 0032ActiveMQ之java编码实现生产者和消费者操作队列queue
今天学习了入门级的用java编写生产者producer和消费者consumer操作activemq的queue队列,为了之后复习回顾,现做整理如下: maven工程的搭建此处不再讲解,在maven工程 ...
- python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型
线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...
- Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程
队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构. get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = ...
- Python进阶【第二篇】多线程、消息队列queue
1.Python多线程.多进程 目的提高并发 1.一个应用程序,可以有多进程和多线程 2.默认:单进程,单线程 3.单进程,多线程 IO操作,不占用CPU python的多线程:IO操作,多线程提供并 ...
随机推荐
- ajax与302响应
在ajax请求中,如果服务器端的响应是302 Found,在ajax的回调函数中能够获取这个状态码吗?能够从Response Headers中得到Location的值进行重定向吗?让我们来一起看看实际 ...
- UFLDL 教程学习笔记(一)
ufdl的新教程,从基础学起.第一节讲的是线性回归.主要目的是熟悉目标函数,计算梯度和优化. 按着教程写完代码后,总是编译出错,一查是mex的原因,实在不想整了. 这位博主用的是向量,比较简洁:htt ...
- windows 2008 启用.NET Framework 3.5
Win2008下已经集成了.NET 3.5.1 framework,需要在管理界面打开! 方法和步骤是: 服务器管理器 -> 功能 -> 添加功能 然后在“选择功能”界面勾选“.NET F ...
- 1 、在Linux(centos6.8)系统下的JDK安装与配置
一.解压jdk安装包: 附上jdk1.8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21 ...
- **linux实用命令之如何移动文件夹及文件下所有文件
http://www.linuxde.net/2013/02/12448.html 格式: mv [选项(option)] 源文件或目录 目标文件或目录 使用命令: mv webdata /bin/u ...
- 【LOJ】#2109. 「JLOI2015」骗我呢
题解 我深思熟虑许久才算是明白个大概的计数问题吧 先是转化成一个矩形,列一条直线y = x,y = x - (m + 1)我们从(0,0)走到(n + m + 1,m + 1)就是答案 因为我们起始相 ...
- 008 jquery过滤选择器-----------(子元素过滤选择器)
1.介紹 2.程序 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- Java动态性之反射机制(reflection)
说到反射机制,第一次接触的人可能会比较懵,反射?什么反射?怎么反射?反射是干嘛的?下面我将在这篇文章中讲讲Java的反射机制 不过在这之前,还有一个问题需要解决,标题名中的动态性,说起动态性,我先介绍 ...
- Bootstrap css-表格
前言:整理的东西比较基础,有不足的地方欢迎大家批评指正! 1,Bootstrap基本的表格结构 源代码: <table class="table"> <cap ...
- HTTP错误405
405 - 用来访问本页面的(方法不被允许) HTTP 错误 405 -禁止访问资源 HTTP 错误 405 405 不允许此方法 对于请求所标识的资源,不允许使用请求行中所指定的方法.请确保为所请求 ...