模拟环境:
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 }
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)); } } } }
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 }
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 }
调用方法:
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: ProductModel代码少上传了
@田麦成: 已经重新上传~
目测多个工人并发装箱时会有问题,装箱过程应该提炼出来,处理发送逻辑。发送给缓冲区队列不能Clear(),应该换一个箱子