代码改变世界

C# 生产者消费者模式 自己写的一个Demo

2016-01-06 17:17  Lasthelloworld  阅读(793)  评论(0)    收藏  举报

模拟环境:

Worker--生产工人

Customer--消费者

WorkQueue--缓存队列

模拟两个工人不停生产产品,生产5个产品装为一箱,放入缓存队列,若队列中有10箱时(满),让工人等待1秒再继续检查队列是否满,不为满时继续生产。 

模拟消费者不停从缓存队列中取东西,若队列为空时,等待工人生产,等待时间4秒。

以下是代码:

Worker--生产工人

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using CommonHelper.Common;
using System.Threading;

namespace DesignModel.WorkerAndCustomerDemo
{


    /// <summary>
    /// 产品类名
    /// </summary>
    public enum ProductType
    { 
      Phone,
      Computer,
       Pad
    }

   /// <summary>
   /// 生产者
   /// </summary>
   public class Worker
   {

       #region 属性
       //生产者名
        private string _Name;

        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        //生产盒子
        private List<ProductModel> _ProductBox;

        //工作队列
        private WorkQueue<List<ProductModel>> _queue;

        //工作线程
        public Thread _thread;

        //生产者等待时间
        private  int Speed = 1000;

       #endregion


        public Worker(WorkQueue<List<ProductModel>> queue)
        {
            this._queue = queue;
            _ProductBox = new List<ProductModel>();
            _thread = new Thread(new ThreadStart(Start));
        }


       //开始工作
        private void Start()
        {

            while (true)
            {
                if (!IsWait())
                {
                    ProductModel product = CreateProduct();
                    InsertBox(product);
                }
                else
                {
                    Thread.Sleep(Speed);//生产者等待时间
                    Console.WriteLine(string.Format("{0} Wait for Working",_thread.Name));
                }
            }
        }

       /// <summary>
       /// 队列满时,线程进入等待10秒
       /// </summary>
       /// <returns></returns>
        private bool IsWait()
        {
            return _queue.MaxSize == _queue.Count;
        }

        //生成一个产品
        public ProductModel CreateProduct()
        {

            int randomindex = RandomHelper.GetIntRandom(1, 4);

            ProductType productType = (ProductType)randomindex;
            ProductModel product = new ProductModel()
            {
                Id = System.Guid.NewGuid().ToString(),
                Name = SelectProductType(productType),
                CreateBy = this._Name,
                DateTime = DateTime.Now
            };

            return product;
        }

        //装箱发送
        public void InsertBox(ProductModel product)
        {
          
            //小于5个产品,都装箱
            if (_ProductBox.Count < 5)
            {
                _ProductBox.Add(product);
                Console.WriteLine(string.Format("{0}生产产品正在装箱",this.Name));
            }
            else
            {
                    Send();
                    Console.WriteLine(string.Format("{0}装满一箱放入队列", this.Name));
                 
            }
        }

       //发送给缓冲区队列
        public void Send()
        {
            List<ProductModel> list =new List<ProductModel>();//地址传递必须重新赋值操作---深拷贝

            foreach (ProductModel item in _ProductBox)
            {
                list.Add(item);
            }

            _queue.EnqueueBox(list);
            _ProductBox.Clear();//清空盒子
        }

        /// 随机获取产品名
        public string SelectProductType(ProductType TypeIndex)
        {
            ProductType productType = ProductType.Phone;

            switch (TypeIndex)
            {
                case ProductType.Phone: productType = ProductType.Phone; break;
                case ProductType.Computer: productType = ProductType.Computer; break;
                case ProductType.Pad: productType = ProductType.Pad; break;
                default: productType = ProductType.Phone; break;
            }

            return productType.ToString();
        }
      

    }
}
Worker

Customer--消费者

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DesignModel.WorkerAndCustomerDemo
{
    /// <summary>
    /// 消费者
    /// </summary>
   public class Customer
   {

       #region 属性
       //消费者名
        private string _Name;

        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        //产品缓存队列
        private WorkQueue<List<ProductModel>> _queue;

       //消费线程
        public Thread _thread;

       //消费者等待时间
        private int Spead = 5000;//消费者等待时间

       #endregion

        public Customer(WorkQueue<List<ProductModel>> queue)
        {
            this._queue = queue;
            _thread = new Thread(new ThreadStart(Start));
            _thread.Name = "消费者";
        }


        public void Start()
        {
            while (true)
            {
                if (!IsWait())
                {
                    Cusum();  
                }
                else
                {
                    Thread.Sleep(Spead);
                    Console.WriteLine(string.Format("{0} Wait for Cusuming", _thread.Name));
                }
            }
        }

        public bool IsWait()
        {
            return _queue.IsEmpty;
        }

        public void Cusum()
        {
            List<ProductModel> box = this._queue.TryDequeueBox();

            if (box != null && box.Count>0)
            {
                foreach (ProductModel item in box)
                {
                    //Console.WriteLine(string.Format("消费了一个箱子中的一个产品:{0}", item.Name));

                }
                Console.WriteLine(string.Format("消费了一个箱子中的一个产品:{0}", box[0].Name));
            }
        }
    }
}
Customer

WorkQueue--缓存队列

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


using System.Collections.Concurrent;
using System.Threading;//线程安全队列.net4.0后

namespace DesignModel.WorkerAndCustomerDemo
{

    /// <summary>
    /// 缓冲区队列
    /// 由生产者和消费者共享
    /// </summary>
    public class WorkQueue<T> :ConcurrentQueue<T>
    {
        /// <summary>
        /// 队列工作形式
        /// </summary>
        public enum WorkType
        {
            Add,
            Get,
            NotAciton
        }

        public int MaxSize = 10;//队列最大值
        
        private static readonly object _Lockobj = new object();//锁对象



        /// <summary>
        /// 尝试移除并返回位于 ConcurrentQueue<T> 开始处的对象
        /// </summary>
        /// <returns></returns>
        public T TryDequeueBox()
        {
            T _obj = default(T);
            if (!this.IsEmpty)//如果队列不为空,也就是有产品
                this.TryDequeue(out _obj);
 
            return _obj;
        }

        /// <summary>
        /// 将箱子添加到队列末尾处
        /// </summary>
        /// <returns></returns>
        public void EnqueueBox(T box)
        {
         
            if (this.MaxSize > this.Count)
            {
                this.Enqueue(box);
            }
        }

       

    }
}
WorkQueue

调用方法:

            WorkQueue<List<ProductModel>> quere = new WorkQueue<List<ProductModel>>();
            //创建工人和消费者
            Customer customer = new Customer(quere);
            Worker w1 = new Worker(quere);
            Worker w2 = new Worker(quere);
            //设置属性
            w1.Name = "工人1";
            w1._thread.Name = "工人1线程";
            w2.Name = "工人2";
            w2._thread.Name = "工人2线程";
            //启动
            w1._thread.Start();
            w2._thread.Start();
            customer._thread.Start();

            Console.Read();

 

以上是本人完成的代码:

下面有几个疑问,问下吧友:

1.如何使用C#事件委托,消息通知的方式完成上面的代码,例如,队列满时,事件通知生产者等待。

2.线程并发时,如何线程之间通讯,例如工人1给工人2之间。

3.目前装箱的过程中,会出现两个工人装一个箱子的情况,请问有没有办法让每个工人独享当前箱子。