zoukankan      html  css  js  c++  java
  • 设计模式—生产者消费者模式

    生产者消费者模式是指生产者和消费者通过一个缓冲区(一般是一个队列)的进行通讯。生产者生产完数据之后不用等待消费者处理。直接放到缓冲区,消费者不找生产者要数据,而是直接从缓冲区里取,这样既能够保持生产者和消费者的并发处理,也能够平衡生产者和消费者的处理能力。

    这样做有下面优点:

    ◇ 减少生产者和消费者之间的耦合性

    假设生产者和消费者各自是两个类。假设让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来假设消费者的代码发生变化,可能会影响到生产者。而假设两者都依赖于某个缓冲区,两者之间不直接依赖。耦合也就对应减少了。

    ◇ 生产者和消费者能够并行执行

    生产者直接与消费者通信的话,因为函数调用是同步的(或者叫堵塞的),在消费者的方法没有返回之前。生产者仅仅好一直等在那边。万一消费者处理数据非常慢,生产者就会白白糟蹋大好时光。

    使用了生产者/消费者模式之后。生产者和消费者能够是两个独立的并发主体(常见并发类型有进程和线程两种,后面的帖子会讲两种并发类型下的应用)。生产者把制造出来的数据往缓冲区一丢。就能够再去生产下一个数据。基本上不用依赖消费者的处理速度。

    ◇ 平衡生产者和消费者的处理能力

    缓冲区还有还有一个优点。假设制造数据的速度时快时慢,缓冲区的优点就体现出来了。当数据制造快的时候。消费者来不及处理,未处理的数据能够暂时存在缓冲区中。等生产者的制造速度慢下来。消费者再慢慢处理掉。

    下面是一个简单的样例。不包括锁机制

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace DesignPatern
    {
        //队列暂时类
        public class QueueInfo
        {
            public string ID { get; set; }
    
            public override string ToString()
            {
                return this.ID;
            }
        }
    
        public class BusinessInfoHelper
        {
            #region 解决公布时含有优质媒体时,前台页面卡住的现象
            //原理:利用生产者消费者模式进行入列出列操作
    
            public readonly static BusinessInfoHelper Instance = new BusinessInfoHelper();
            private int N = 100;
            private BusinessInfoHelper()
            {
            }
    
            private Queue<QueueInfo> ListQueue = new Queue<QueueInfo>();
    
            public void StartProducer()
            {
                Thread thread = new Thread(threadStartProduct);
                thread.Start();
            }
    
            private void threadStartProduct()
            {
                int k = 0;
                while(true)
                {
                    if(ListQueue.Count<N)
                    {
                        try
                        {
                            k++;
                            AddQueue(k.ToString());
                        }
                        catch(Exception ex)
                        {
                            throw new Exception(ex.ToString());
                        }
                    }
                }
            }
    
            public void AddQueue(string pid) //入列
            {
                QueueInfo queueinfo = new QueueInfo();
    
                queueinfo.ID = pid;
                ListQueue.Enqueue(queueinfo);
            }
    
            public void StartConsumer()//启动
            {
                Thread thread = new Thread(threadStartConsume);
                thread.IsBackground = true;
                thread.Start();
            }
    
            private void threadStartConsume()
            {
                while (true)
                {
                    if (ListQueue.Count > 0)
                    {
                        try
                        {
                            ScanQueue();
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(ex.Message);
                        }
                    }
                    else
                    {
                        //没有任务,歇息3秒钟
                        Thread.Sleep(3000);
                    }
                }
            }
    
            //要执行的方法
            private void ScanQueue()
            {
                while (ListQueue.Count > 0)
                {
                    try
                    {
                        //从队列中取出
                        QueueInfo queueinfo = ListQueue.Dequeue();
                        Console.WriteLine(queueinfo.ToString());
                        //取出的queueinfo就能够用了,里面有你要的东西
                        //下面就是处理程序了
                        //。

    。。。

    。。 } catch (Exception ex) { throw new Exception(ex.ToString()); } } } #endregion } }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace DesignPatern
    {
        class Program
        {
            private static object lockObject = new Object(); 
            static void Main(string[] args)
            {
                DesignPatern.BusinessInfoHelper.Instance.StartProducer();
                DesignPatern.BusinessInfoHelper.Instance.StartConsumer();
                //Thread.Sleep(300000);
            }
        }
    }

    写的不完整等待兴许完好。

    。。

    參考资料:
    http://blog.csdn.net/kaiwii/article/details/6758942
    http://www.infoq.com/cn/articles/producers-and-consumers-mode/#0-tsina-1-97643-397232819ff9a47a7b7e80a40613cfe1

  • 相关阅读:
    如何实现文字两端对齐?
    三目运算符的复杂运算(条件嵌套判断)
    微信小程序实现图片上传,预览,删除
    微信小程序滚动条返回顶部
    vue+axios下载文件的实现
    java script 运算符
    关于placeholder提示内容出现在textarea底部问题
    js基础知识
    java script 字符串
    java script 函数
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7103174.html
Copyright © 2011-2022 走看看