本篇体验使用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实现生产消费模式的更多相关文章

  1. C# 队列Queue,ConcurrentQueue,BlockingCollection 并发控制lock,Monitor,信号量Semaphore

    什么是队列? 队列Queues,是一种遵循先进先出的原则的集合,在.netCore中微软给我们提供了很多个类,就目前本人所知的有三种,分别是标题提到的:Queue.ConcurrentQueue.Bl ...

  2. 消息队列Queue大全

    消息队列Queue大全 (http://queues.io/) 作业队列,消息队列和其他队列.几乎所有你能想到的都在这. 关于 那里有很多排队系统.他们每个人都不同,是为解决某些问题而创建的.这个页面 ...

  3. 使用队列queue实现一个简单的生产者消费者模型

    一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...

  4. Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)

    1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...

  5. 线程队列queue

    队列queue 队列用于线程之间安全的信息交换 队列和列表的区别:队列里的信息get()后就没了,而列表获取数据则是copy,原列表里的值还在 使用前先实例化队列 q = queue.Queue(ma ...

  6. 0032ActiveMQ之java编码实现生产者和消费者操作队列queue

    今天学习了入门级的用java编写生产者producer和消费者consumer操作activemq的queue队列,为了之后复习回顾,现做整理如下: maven工程的搭建此处不再讲解,在maven工程 ...

  7. python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型

    线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...

  8. Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

    队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构. get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = ...

  9. Python进阶【第二篇】多线程、消息队列queue

    1.Python多线程.多进程 目的提高并发 1.一个应用程序,可以有多进程和多线程 2.默认:单进程,单线程 3.单进程,多线程 IO操作,不占用CPU python的多线程:IO操作,多线程提供并 ...

随机推荐

  1. 基于FPGA(DDS)的正弦波发生器

    记录背景:昨晚快下班时,与同事rk聊起怎么用FPGA实现正弦波的输出.我第一反应是利用高频的PWM波去滤波,但感觉这样的波形精度肯定很差:后来想起之前由看过怎么用FPGA产生正弦波的技术,但怎么都想不 ...

  2. 二维码扫描开源库ZXing定制化【转】

    转自:http://www.cnblogs.com/sickworm/p/4562081.html 最近在用ZXing这个开源库做二维码的扫描模块,开发过程的一些代码修改和裁剪的经验和大家分享一下. ...

  3. ntpdate时间同步

    为什么需要网络同步时间: Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用nt ...

  4. 一个浏览器Fuzzing框架的学习

    一个浏览器Fuzzing框架的学习 关于框架 之前是LCatro师傅在小密圈分享的他写的这个Fuzzing框架(不过我以前翻github时好像就看到过),但是之前一直没啥时间搞这方面,这两天研究学习了 ...

  5. stm32+ESP8266AT指令详细说明

    最近公司团队的项目用到ESP8266,使用的是stm32c8t6芯片,软件使用MDK,于是写下调试过程中的一些注意点.具体代码和涉及思路不能外泄,这里只给出我们调试过程中的注意的方面. 关于ESP82 ...

  6. Codeforces 623B Array GCD

    Array GCD 最后的序列里肯定有a[1], a[1]-1, a[1]+1, a[n], a[n]-1, a[n]+1中的一个,枚举质因子, dp去check #include<bits/s ...

  7. SpringBoot属性配置

    一:url的配置 1.配置 默认配置文件是application.properties 2.配置 配置端口 配置context path 3.启动效果 4.第二种配置方式 要先删除applicatio ...

  8. Java 持久化之 -- IO 全面整理(看了绝不后悔)

    目录: 一.java io 概述 什么是IO? IO包括输入流和输出流,输入流指的是将数据以字符或者字节形式读取到内存 分为字符输入流和字符输入流 输入流指的是从内存读取到外界 ,分为字符输入流和字节 ...

  9. Java日志记录--log4j and logback

    问题的引入: 把所有的信息打印在控制台上不行吗? 01.控制台有行数限制: 02.System.out.println()影响系统性能: 03.如果我们需要对一些用户的行为习惯进行分析,我们找不到用户 ...

  10. codevs 2821 天使之城

    题目描述 Description 天使城有一个火车站,每辆火车都从A方向驶入车站,再从B方向驶出车站. 为了调度火车,火车站设有停放轨道,可存放5辆火车.已知从A进入车站顺序为1.2.3…….现在给你 ...