C# 使用ManualResetEvent 实现多线程的生产消费
变量命名使用中文。更容易理解。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
using System.Threading;
namespace 使用ManualResetEvent实现生产消费
{
class Program
{
static void Main(string[] args)
{
var 青铜生产商 = new 青铜生产商();
var 白银生产商 = new 白银生产商();
var 黄金生产商 = new 黄金生产商();
var 青铜消费者 = new 消费者(5000);
var 白银消费者 = new 消费者(3000);
var 黄金消费者 = new 消费者(1000);
Parallel.Invoke(() => 青铜生产商.生产(), () => 白银生产商.生产(), () => 黄金生产商.生产(), () => 青铜消费者.消费(), () => 白银消费者.消费(), () => 黄金消费者.消费());
WriteLine("END");
ReadLine();
}
}
public static class 商品
{
private static readonly object locker = new object();
private static Queue<int> list = new Queue<int>();
private static int No = 0;
public static int GetCount()
{
lock (locker)
{
int i;
i = list.Count;
return i;
}
}
public static int GetProduct()
{
lock (locker)
{
int i;
i = list.Dequeue();
return i;
}
}
public static int AddProduct()
{
lock (locker)
{
int i;
i = No++;
list.Enqueue(i);
return i;
}
}
}
#region 生产者
public abstract class 生产者
{
private static ManualResetEvent 生产控制 = new ManualResetEvent(false);
public abstract int 生产时间 { get; }
public void 生产()
{
for (int i = 0; i < 10; i++)
{
WriteLine($"本次花{生产时间},生产出了【{商品.AddProduct()}】");
Thread.Sleep(生产时间);
if (商品.GetCount() == 10)
{
控制中心.开始消费();
}
}
}
}
public class 青铜生产商 : 生产者
{
public override int 生产时间 { get => 5000; }
}
public class 白银生产商 : 生产者
{
public override int 生产时间 { get => 3000; }
}
public class 黄金生产商 : 生产者
{
public override int 生产时间 { get => 1000; }
}
#endregion
#region 消费者
public class 消费者
{
private readonly int 消费时间;
public 消费者(int 消费时间)
{
this.消费时间 = 消费时间;
}
public void 消费()
{
控制中心.停止消费();
while (true)
{
if (商品.GetCount() > 0)
{
WriteLine($"本次花{消费时间},消费掉了{商品.GetProduct()}");
Thread.Sleep(消费时间);
}
else
{
break;
}
}
Console.WriteLine($"消费者结束{Thread.CurrentThread.ManagedThreadId}");
}
}
#endregion
#region 控制中心
public static class 控制中心
{
private static ManualResetEvent 消费控制 = new ManualResetEvent(false);
public static bool 是否停产 = false;
public static void 开始消费()
{
WriteLine("开始消费");
消费控制.Set();
}
public static void 停止消费()
{
消费控制.WaitOne();
}
}
#endregion
}