首页 新闻 搜索 专区 学院

自己用C#写的生产者消费者模式DEMO,请求大神优化

0
[待解决问题]

模拟环境:

Worker--生产工人

Customer--消费者

WorkQueue--缓存队列

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

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

以下是代码:

Worker--生产工人

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 
  6 using CommonHelper.Common;
  7 using System.Threading;
  8 
  9 namespace DesignModel.WorkerAndCustomerDemo
 10 {
 11 
 12 
 13     /// <summary>
 14     /// 产品类名
 15     /// </summary>
 16     public enum ProductType
 17     { 
 18       Phone,
 19       Computer,
 20        Pad
 21     }
 22 
 23    /// <summary>
 24    /// 生产者
 25    /// </summary>
 26    public class Worker
 27    {
 28 
 29        #region 属性
 30        //生产者名
 31         private string _Name;
 32 
 33         public string Name
 34         {
 35             get { return _Name; }
 36             set { _Name = value; }
 37         }
 38 
 39         //生产盒子
 40         private List<ProductModel> _ProductBox;
 41 
 42         //工作队列
 43         private WorkQueue<List<ProductModel>> _queue;
 44 
 45         //工作线程
 46         public Thread _thread;
 47 
 48         //生产者等待时间
 49         private  int Speed = 1000;
 50 
 51        #endregion
 52 
 53 
 54         public Worker(WorkQueue<List<ProductModel>> queue)
 55         {
 56             this._queue = queue;
 57             _ProductBox = new List<ProductModel>();
 58             _thread = new Thread(new ThreadStart(Start));
 59         }
 60 
 61 
 62        //开始工作
 63         private void Start()
 64         {
 65 
 66             while (true)
 67             {
 68                 if (!IsWait())
 69                 {
 70                     ProductModel product = CreateProduct();
 71                     InsertBox(product);
 72                 }
 73                 else
 74                 {
 75                     Thread.Sleep(Speed);//生产者等待时间
 76                     Console.WriteLine(string.Format("{0} Wait for Working",_thread.Name));
 77                 }
 78             }
 79         }
 80 
 81        /// <summary>
 82        /// 队列满时,线程进入等待10秒
 83        /// </summary>
 84        /// <returns></returns>
 85         private bool IsWait()
 86         {
 87             return _queue.MaxSize == _queue.Count;
 88         }
 89 
 90         //生成一个产品
 91         public ProductModel CreateProduct()
 92         {
 93 
 94             int randomindex = RandomHelper.GetIntRandom(1, 4);
 95 
 96             ProductType productType = (ProductType)randomindex;
 97             ProductModel product = new ProductModel()
 98             {
 99                 Id = System.Guid.NewGuid().ToString(),
100                 Name = SelectProductType(productType),
101                 CreateBy = this._Name,
102                 DateTime = DateTime.Now
103             };
104 
105             return product;
106         }
107 
108         //装箱发送
109         public void InsertBox(ProductModel product)
110         {
111           
112             //小于5个产品,都装箱
113             if (_ProductBox.Count < 5)
114             {
115                 _ProductBox.Add(product);
116                 Console.WriteLine(string.Format("{0}生产产品正在装箱",this.Name));
117             }
118             else
119             {
120                     Send();
121                     Console.WriteLine(string.Format("{0}装满一箱放入队列", this.Name));
122                  
123             }
124         }
125 
126        //发送给缓冲区队列
127         public void Send()
128         {
129             List<ProductModel> list =new List<ProductModel>();//地址传递必须重新赋值操作---深拷贝
130 
131             foreach (ProductModel item in _ProductBox)
132             {
133                 list.Add(item);
134             }
135 
136             _queue.EnqueueBox(list);
137             _ProductBox.Clear();//清空盒子
138         }
139 
140         /// 随机获取产品名
141         public string SelectProductType(ProductType TypeIndex)
142         {
143             ProductType productType = ProductType.Phone;
144 
145             switch (TypeIndex)
146             {
147                 case ProductType.Phone: productType = ProductType.Phone; break;
148                 case ProductType.Computer: productType = ProductType.Computer; break;
149                 case ProductType.Pad: productType = ProductType.Pad; break;
150                 default: productType = ProductType.Phone; break;
151             }
152 
153             return productType.ToString();
154         }
155       
156 
157     }
158 }
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--缓存队列

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 
 7 using System.Collections.Concurrent;
 8 using System.Threading;//线程安全队列.net4.0后
 9 
10 namespace DesignModel.WorkerAndCustomerDemo
11 {
12 
13     /// <summary>
14     /// 缓冲区队列
15     /// 由生产者和消费者共享
16     /// </summary>
17     public class WorkQueue<T> :ConcurrentQueue<T>
18     {
19         /// <summary>
20         /// 队列工作形式
21         /// </summary>
22         public enum WorkType
23         {
24             Add,
25             Get,
26             NotAciton
27         }
28 
29         public int MaxSize = 10;//队列最大值
30         
31         private static readonly object _Lockobj = new object();//锁对象
32 
33 
34 
35         /// <summary>
36         /// 尝试移除并返回位于 ConcurrentQueue<T> 开始处的对象
37         /// </summary>
38         /// <returns></returns>
39         public T TryDequeueBox()
40         {
41             T _obj = default(T);
42             if (!this.IsEmpty)//如果队列不为空,也就是有产品
43                 this.TryDequeue(out _obj);
44  
45             return _obj;
46         }
47 
48         /// <summary>
49         /// 将箱子添加到队列末尾处
50         /// </summary>
51         /// <returns></returns>
52         public void EnqueueBox(T box)
53         {
54          
55             if (this.MaxSize > this.Count)
56             {
57                 this.Enqueue(box);
58             }
59         }
60 
61        
62 
63     }
64 }
WorkQueue

 ProductModel

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace DesignModel.WorkerAndCustomerDemo
 7 {
 8     /// <summary>
 9     /// 生产者生产的产品
10     /// 
11     /// </summary>
12    public class ProductModel
13     {
14        /// <summary>
15        /// 产品ID
16        /// </summary>
17         private string _Id;
18 
19         public string Id
20         {
21             get { return _Id; }
22             set { _Id = value; }
23         }
24        /// <summary>
25        /// 产品名
26        /// </summary>
27         private string _Name;
28 
29         public string Name
30         {
31             get { return _Name; }
32             set { _Name = value; }
33         }
34        /// <summary>
35        /// 哪位生产者创建的
36        /// </summary>
37         private string _CreateBy;
38 
39         public string CreateBy
40         {
41             get { return _CreateBy; }
42             set { _CreateBy = value; }
43         }
44 
45        /// <summary>
46        /// 创建的时间
47        /// </summary>
48         private DateTime _DateTime;
49 
50         public DateTime DateTime
51         {
52             get { return _DateTime; }
53             set { _DateTime = value; }
54         }
55     }
56 }
ProductModel

 

调用方法:

            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.目前装箱的过程中,会出现两个工人装一个箱子的情况,请问有没有办法让每个工人独享当前箱子。

4.目前工人和消费者在队列不满足各自条件的时候,都是等待,每个工人线程和消费者线程都是运行中,如何把sleep改装为线程阻塞唤醒模式呢

Lasthelloworld的主页 Lasthelloworld | 初学一级 | 园豆:92
提问于:2016-01-06 17:20
< >
分享
所有回答(2)
0

你上传的代码,你自己能看到么? 你自己能点开么?反正我这边点不开,看不到

田麦成 | 园豆:2015 (老鸟四级) | 2016-01-07 08:50

恩,谢谢,提醒,提交的时候,有错误,现在可以了

支持(0) 反对(0) Lasthelloworld | 园豆:92 (初学一级) | 2016-01-07 09:55

@Lasthelloworld: ProductModel代码少上传了

支持(0) 反对(0) 田麦成 | 园豆:2015 (老鸟四级) | 2016-01-07 10:26

@田麦成: 已经重新上传~

支持(0) 反对(0) Lasthelloworld | 园豆:92 (初学一级) | 2016-01-07 10:48
0

目测多个工人并发装箱时会有问题,装箱过程应该提炼出来,处理发送逻辑。发送给缓冲区队列不能Clear(),应该换一个箱子

bestzhao点com | 园豆:204 (菜鸟二级) | 2016-01-21 10:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册