C#使用泛型隊列Queue實現(xiàn)生產(chǎn)消費模式
如果把生產(chǎn)消費想像成自動流水生產(chǎn)線的話,生產(chǎn)就是流水線的物料,消費就是某種設備對物料進行加工的行為,流水線就是隊列。
現(xiàn)在,要寫一個體現(xiàn)生產(chǎn)消費模式的泛型幫助類,比如叫ProducerConsumer<T>。
該類肯定會維護一個有關生產(chǎn)、物料的Queue<T>類型的字段,還存在一個有關消費、Action<T>類型的字段。
在ProducerConsumer類的構造函數(shù)中,為Action<T>類型的字段賦值,并開啟后臺有關消費的線程。
ProducerConsumer類肯定存在一個進隊列的方法,并且要保證在多線程情況下,同一時間只有一個生產(chǎn)或物料進入隊列。
ProducerConsumer類還存在一個有關消費的方法,并且保證在多線程情況下,同一時間只有一個生產(chǎn)或物料出列,并消費它。
另外,在生產(chǎn)或物料在出隊列的時候,可能會出現(xiàn)隊列中暫時沒有生產(chǎn)或物料的情況,這時候我們希望線程阻塞一下,這需要通過AutoResetEvent實現(xiàn)。AutoResetEvent的大致原理是:當生產(chǎn)或物料進入隊列的時候需要告訴AutoResetEvent一下,當隊列中暫時沒有生產(chǎn)或物料的時候,也需要告訴AutoResetEvent,讓它來阻塞線程。
//有關生產(chǎn)消費的泛型類
public class ProducerConsumer<T>
{
//用來存儲生產(chǎn)者的隊列
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;
//后臺開啟一個線程開始消費生產(chǎn)者
new Thread(this.ConsumeItems){IsBackground = true}.Start();
}
//進列
public void Enqueue(T item)
{
//確保同一時間只有一個生產(chǎn)者進列
lock (queueLocker)
{
queue.Enqueue(item);
//每次進列都要設置AutoResetEvent事件
this.queueWaitHandle.Set();
}
}
//消費動作
private void ConsumeItems()
{
while (true)
{
T nextItem = default(T);
//標志,確認隊列中的生產(chǎn)者是否存在
bool doesItemExist;
//確保同一時間只有一個生產(chǎn)者出列
lock (this.queueLocker)
{
//先確認隊列中的生產(chǎn)者是否存在
doesItemExist = this.queue.Count > 0;
if (doesItemExist)
{
nextItem = this.queue.Dequeue();
}
}
//如果生產(chǎn)者存在,才消費生產(chǎn)者
if (doesItemExist)
{
this.consumerAction(nextItem);
}
else//否則的話,再等等下一個隊列中的生產(chǎn)者
{
this.queueWaitHandle.WaitOne();
}
}
}
}客戶端,針對多線程情形。
class Program
{
static void Main(string[] args)
{
//實例化一個int類型的生產(chǎn)消費實例
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();
}
}以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內(nèi)容請查看下面相關鏈接
相關文章
c# 調(diào)用Surfer軟件,添加引用的具體操作方法
本篇文章主要是對c#中調(diào)用Surfer軟件,添加引用的具體操作方法進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01
C#短時間內(nèi)產(chǎn)生大量不重復的隨機數(shù)
在C#編程中,經(jīng)常會碰到產(chǎn)生隨機數(shù)的情況,并且是在短時間內(nèi)產(chǎn)生一組隨機數(shù)。如果這組隨機數(shù)中有大量重復的,則達不到我們的要求2013-02-02
解析C#多線程編程中異步多線程的實現(xiàn)及線程池的使用
這篇文章主要介紹了C#多線程編程中異步多線程的實現(xiàn)及線程池的使用,同時對多線程的一般概念及C#中的線程同步并發(fā)編程作了講解,需要的朋友可以參考下2016-03-03
asp.net core 使用 tensorflowjs實現(xiàn) face recognition的源代碼
tensorflowjs,在該項目中使用了ml5js這個封裝過的機器學習JavaScript類庫, 使用起來更簡單,本文給大家分享asp.net core 使用 tensorflowjs實現(xiàn) face recognition的源代碼,需要的朋友參考下吧2021-06-06

