[C.C++] C#使用泛型队列Queue实现生产消费模式

1860 0
黑夜隐士 2022-11-5 08:39:13 | 显示全部楼层 |阅读模式
如果把生产消费想像成自动流水生产线的话,生产就是流水线的物料,消费就是某种设备对物料进行加工的行为,流水线就是队列。
现在,要写一个体现生产消费模式的泛型帮助类,比如叫ProducerConsumer<T>。
该类肯定会维护一个有关生产、物料的Queue<T>类型的字段,还存在一个有关消费、Action<T>类型的字段。
在ProducerConsumer类的构造函数中,为Action<T>类型的字段赋值,并开启后台有关消费的线程。
ProducerConsumer类肯定存在一个进队列的方法,并且要保证在多线程情况下,同一时间只有一个生产或物料进入队列。
ProducerConsumer类还存在一个有关消费的方法,并且保证在多线程情况下,同一时间只有一个生产或物料出列,并消费它。
另外,在生产或物料在出队列的时候,可能会出现队列中暂时没有生产或物料的情况,这时候我们希望线程阻塞一下,这需要通过AutoResetEvent实现。AutoResetEvent的大致原理是:当生产或物料进入队列的时候需要告诉AutoResetEvent一下,当队列中暂时没有生产或物料的时候,也需要告诉AutoResetEvent,让它来阻塞线程。
  1.   //有关生产消费的泛型类
  2.     public class ProducerConsumer<T>
  3.     {
  4.         //用来存储生产者的队列
  5.         private readonly Queue<T>  queue = new Queue<T>();
  6.         //锁
  7.         private readonly object queueLocker = new object();
  8.         //消费行为
  9.         private readonly Action<T> consumerAction;
  10.         //出列的时候需要检查队列中是否有元素,如果没有,需要阻塞
  11.         private readonly AutoResetEvent queueWaitHandle = new AutoResetEvent(false);
  12.         public ProducerConsumer(Action<T> consumerAction)
  13.         {
  14.             if (consumerAction == null)
  15.             {
  16.                 throw new ArgumentNullException("consumerActin");
  17.             }
  18.             this.consumerAction = consumerAction;
  19.             //后台开启一个线程开始消费生产者
  20.             new Thread(this.ConsumeItems){IsBackground = true}.Start();
  21.         }
  22.         //进列
  23.         public void Enqueue(T item)
  24.         {
  25.             //确保同一时间只有一个生产者进列
  26.             lock (queueLocker)
  27.             {
  28.                 queue.Enqueue(item);
  29.                 //每次进列都要设置AutoResetEvent事件
  30.                 this.queueWaitHandle.Set();
  31.             }
  32.         }
  33.         //消费动作
  34.         private void ConsumeItems()
  35.         {
  36.             while (true)
  37.             {
  38.                 T nextItem = default(T);
  39.                 //标志,确认队列中的生产者是否存在
  40.                 bool doesItemExist;
  41.                 //确保同一时间只有一个生产者出列
  42.                 lock (this.queueLocker)
  43.                 {
  44.                     //先确认队列中的生产者是否存在
  45.                     doesItemExist = this.queue.Count > 0;
  46.                     if (doesItemExist)
  47.                     {
  48.                         nextItem = this.queue.Dequeue();
  49.                     }
  50.                 }
  51.                 //如果生产者存在,才消费生产者
  52.                 if (doesItemExist)
  53.                 {
  54.                     this.consumerAction(nextItem);
  55.                 }
  56.                 else//否则的话,再等等下一个队列中的生产者
  57.                 {
  58.                     this.queueWaitHandle.WaitOne();
  59.                 }
  60.             }
  61.         }
  62.     }
复制代码
客户端,针对多线程情形。
  1.     class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             //实例化一个int类型的生产消费实例
  6.             var producerConsumer = new ProducerConsumer<int>(i => Console.WriteLine("正在消费" + i));
  7.             Random random = new Random();
  8.             //开启进队列线程
  9.             var t1 = new Thread(() =>
  10.             {
  11.                 for (int i = 0; i < 100; i++)
  12.                 {
  13.                     producerConsumer.Enqueue(i);
  14.                     Thread.Sleep(random.Next(0,5));
  15.                 }
  16.             });
  17.             var t2 = new Thread(() =>
  18.             {
  19.                 for (int i = 0; i > -100; i--)
  20.                 {
  21.                     producerConsumer.Enqueue(i);
  22.                     Thread.Sleep(random.Next(0, 5));
  23.                 }
  24.             });
  25.             t1.Start();
  26.             t2.Start();
  27.             t1.Join();
  28.             t2.Join();
  29.             Thread.Sleep(50);
  30.             Console.ReadKey();
  31.         }
  32.     }
复制代码
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对中国红客联盟的支持。如果你想了解更多相关内容请查看下面相关链接
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行