使用事件AutoResetEvent/ManualResetEvent
假如一个线程处理任务,保持了一个任务队列;其它几个线程向该任务队列中添加任务。
我们要保证这个任务队列不能过大,比如每一个时刻,只能有3个任务在队列中,使用事件
(AutoResetEvent/ManualResetEvent)机制如下:
namespace ManualResetEventTest
{
class Program
{
static void Main(string[] args)
{
Process processObj = new Process();
ThreadStart newProcessStart = new ThreadStart(processObj.ProcessTask);
Thread newThread = new Thread(newProcessStart);
newThread.Start();
//任务产生线程1
Monitor monitorObj = new Monitor();
monitorObj.processObj = processObj;
ThreadStart newMonitorStart = new ThreadStart(monitorObj.GenerateTask);
Thread newMonitorThread = new Thread(newMonitorStart);
newMonitorThread.Start();
//任务产生线程1
Monitor monitorObj2 = new Monitor();
monitorObj2.processObj = processObj;
ThreadStart newMonitorStart2 = new ThreadStart(monitorObj2.GenerateTask);
Thread newMonitorThread2 = new Thread(newMonitorStart2);
newMonitorThread2.Start();
Console.ReadLine();
}
}
class Task
{
private static int refCount = 0;
private int taskID = 0;
public int TaskID
{
get { return taskID; }
}
public int RefCount
{
get { return refCount; }
}
public Task()
{
refCount++;
taskID = RefCount;
}
}
class Process
{
private Queue<Task> taskList = new Queue<Task>();
private Random random = new Random();
private object obj = new object();
//用于保证任务队列taskList中,始终只有少量任务等待被处理
public ManualResetEvent manualEvent = new ManualResetEvent(true);//初始状态,设置manualEvent被设置为Set
public void ProcessTask()
{
while(true)
{
if (taskList.Count > 0)
{
Console.WriteLine("current task count:{0}", taskList.Count);
Task task = taskList.Dequeue();
ProcessTask(task);
if (taskList.Count < 3)
{
manualEvent.Set(); //任务数量少于3,正在WaitOne的线程可以执行了
}
else
{
manualEvent.Reset();//任务数量太多了,所有线程都得WaitOne
}
}
else
{
Thread.Sleep(2*1000);
}
}
}
private void ProcessTask(Task task)
{
Console.WriteLine("process task ID:{0}",task.TaskID);
Thread.Sleep(random.Next(10) * 1000);//每个任务处理时间,是个0~10之间的随机数
}
public void AddTask(Task task)
{
lock (obj)
{
taskList.Enqueue(task);
if (taskList.Count < 3)
{
manualEvent.Set(); //任务数量少于3,正在WaitOne的线程可以执行了
}
else
{
manualEvent.Reset();//任务数量太多了,所有线程都得WaitOne
}
}
}
}
class Monitor
{
public Process processObj = null;
private Random random = new Random();
private object obj = new object();
public void GenerateTask()
{
while (true)
{
lock (obj)
{
processObj.manualEvent.WaitOne(); //直到manualEvent被Set,才能继续执行
Task task = new Task();
processObj.AddTask(task);
Thread.Sleep(random.Next(3) * 1000);//产生一个任务后,需要不超过3秒钟
}
}
}
}
}