欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#使用泛型隊(duì)列Queue實(shí)現(xiàn)生產(chǎn)消費(fèi)模式

 更新時(shí)間:2022年10月22日 14:50:24   作者:Darren?Ji  
這篇文章介紹了C#使用泛型隊(duì)列Queue實(shí)現(xiàn)生產(chǎn)消費(fèi)模式的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

如果把生產(chǎn)消費(fèi)想像成自動(dòng)流水生產(chǎn)線的話,生產(chǎn)就是流水線的物料,消費(fèi)就是某種設(shè)備對(duì)物料進(jìn)行加工的行為,流水線就是隊(duì)列。

現(xiàn)在,要寫(xiě)一個(gè)體現(xiàn)生產(chǎn)消費(fèi)模式的泛型幫助類,比如叫ProducerConsumer<T>。

該類肯定會(huì)維護(hù)一個(gè)有關(guān)生產(chǎn)、物料的Queue<T>類型的字段,還存在一個(gè)有關(guān)消費(fèi)、Action<T>類型的字段。

在ProducerConsumer類的構(gòu)造函數(shù)中,為Action<T>類型的字段賦值,并開(kāi)啟后臺(tái)有關(guān)消費(fèi)的線程。

ProducerConsumer類肯定存在一個(gè)進(jìn)隊(duì)列的方法,并且要保證在多線程情況下,同一時(shí)間只有一個(gè)生產(chǎn)或物料進(jìn)入隊(duì)列。

ProducerConsumer類還存在一個(gè)有關(guān)消費(fèi)的方法,并且保證在多線程情況下,同一時(shí)間只有一個(gè)生產(chǎn)或物料出列,并消費(fèi)它。

另外,在生產(chǎn)或物料在出隊(duì)列的時(shí)候,可能會(huì)出現(xiàn)隊(duì)列中暫時(shí)沒(méi)有生產(chǎn)或物料的情況,這時(shí)候我們希望線程阻塞一下,這需要通過(guò)AutoResetEvent實(shí)現(xiàn)。AutoResetEvent的大致原理是:當(dāng)生產(chǎn)或物料進(jìn)入隊(duì)列的時(shí)候需要告訴AutoResetEvent一下,當(dāng)隊(duì)列中暫時(shí)沒(méi)有生產(chǎn)或物料的時(shí)候,也需要告訴AutoResetEvent,讓它來(lái)阻塞線程。

  //有關(guān)生產(chǎn)消費(fèi)的泛型類
    public class ProducerConsumer<T>
    {
        //用來(lái)存儲(chǔ)生產(chǎn)者的隊(duì)列
        private readonly Queue<T>  queue = new Queue<T>();
        //鎖
        private readonly object queueLocker = new object();
        //消費(fèi)行為
        private readonly Action<T> consumerAction;
        //出列的時(shí)候需要檢查隊(duì)列中是否有元素,如果沒(méi)有,需要阻塞
        private readonly AutoResetEvent queueWaitHandle = new AutoResetEvent(false);
        public ProducerConsumer(Action<T> consumerAction)
        {
            if (consumerAction == null)
            {
                throw new ArgumentNullException("consumerAction");
            }
            this.consumerAction = consumerAction;
            //后臺(tái)開(kāi)啟一個(gè)線程開(kāi)始消費(fèi)生產(chǎn)者
            new Thread(this.ConsumeItems){IsBackground = true}.Start();
        }
        //進(jìn)列
        public void Enqueue(T item)
        {
            //確保同一時(shí)間只有一個(gè)生產(chǎn)者進(jìn)列
            lock (queueLocker)
            {
                queue.Enqueue(item);
                //每次進(jìn)列都要設(shè)置AutoResetEvent事件
                this.queueWaitHandle.Set();
            }
        }
        //消費(fèi)動(dòng)作
        private void ConsumeItems()
        {
            while (true)
            {
                T nextItem = default(T);
                //標(biāo)志,確認(rèn)隊(duì)列中的生產(chǎn)者是否存在
                bool doesItemExist;
                //確保同一時(shí)間只有一個(gè)生產(chǎn)者出列
                lock (this.queueLocker)
                {
                    //先確認(rèn)隊(duì)列中的生產(chǎn)者是否存在
                    doesItemExist = this.queue.Count > 0;
                    if (doesItemExist)
                    {
                        nextItem = this.queue.Dequeue();
                    }
                    
                }
                //如果生產(chǎn)者存在,才消費(fèi)生產(chǎn)者
                if (doesItemExist)
                {
                    this.consumerAction(nextItem);
                }
                else//否則的話,再等等下一個(gè)隊(duì)列中的生產(chǎn)者
                {
                    this.queueWaitHandle.WaitOne();
                }
                
            }
        }
    }

客戶端,針對(duì)多線程情形。

    class Program
    {
        static void Main(string[] args)
        {
            //實(shí)例化一個(gè)int類型的生產(chǎn)消費(fèi)實(shí)例
            var producerConsumer = new ProducerConsumer<int>(i => Console.WriteLine("正在消費(fèi)" + i));
            Random random = new Random();
            //開(kāi)啟進(jìn)隊(duì)列線程
            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();
        }
    }

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

最新評(píng)論