虽然知道有消息队列的概念,但是还没有实际学习,根据自己的感觉先写了个版本,不知道准确不准确,回头看看这反面的知识,看看实例纠正一下。这样感觉印象更深。
不知道方向对不对,单队列这样处理,在生产前再添加一个并不是特别严格的分拣函数,创建一个多对多的关系应该能实现多生产多消费的感觉。
回头找官方解释和大神代码印证一下。
using System;
using System.Collections;
using System.IO;
using System.Threading;
namespace queue
{
class Program
{
static void Main(string[] args)
{
QueueUtil qu = new QueueUtil();
const int TEMP = 100;
// 任务生产者1
new Thread(state=>{
Random r = new Random();
for(int i = 0; i < TEMP; i++){
// 添加到处理队列
qu.enqueue(j=>{
QueueUtil.writeLine("Thread1: " + j);
}, i);
Thread.Sleep(r.Next(0, 1000));
}
}).Start();
// 任务生产者2
new Thread(state=>{
Random r = new Random();
for(int i = 0; i < TEMP; i++){
// 添加到处理队列
qu.enqueue(j=>{
QueueUtil.writeLine("Thread2: " + j);
}, i);
Thread.Sleep(r.Next(0, 1000));
}
}).Start();
// 任务生产者3
new Thread(state=>{
Random r = new Random();
for(int i = 0; i < TEMP; i++){
// 添加到处理队列
qu.enqueue(j=>{
QueueUtil.writeLine("Thread3: " + j);
}, i);
Thread.Sleep(r.Next(0, 1000));
}
}).Start();
}
}
public class QueueUtil {
public Queue queue; // 队列
public bool isSuspend = true; // 消费者是否挂起
public ReaderWriterLock readerWriterLock; // 消费者状态锁
public int num = 0; // 执行次数记录
public QueueUtil(){
this.init();
}
public void init(){
queue = Queue.Synchronized(new Queue());
readerWriterLock = new ReaderWriterLock();
}
public void enqueue(Action<int> action, int i){
queue.Enqueue(Tuple.Create(action, i)); // 添加任务到队列
readerWriterLock.AcquireReaderLock(Timeout.Infinite);
if(isSuspend){ // 判断消费者是否关闭,避免生产堵塞,使用读锁
readerWriterLock.UpgradeToWriterLock(Timeout.Infinite);
if(isSuspend){ // 消费者关闭时,重新打开,锁修改为写锁,避免重复开启
isSuspend = false;
this.run();
}
}
readerWriterLock.ReleaseLock();
}
private void run(){
new Thread(state=>{
QueueUtil.writeLine("启动");
while(!isSuspend){
if(queue.Count > 0){ // 队列有内容时进行处理
object head = queue.Dequeue();
Tuple<Action<int>, int> item = (Tuple<Action<int>, int>)head;
item.Item1(item.Item2);
num++;
QueueUtil.writeLine("当前执行次数" + num);
}else{
readerWriterLock.AcquireWriterLock(Timeout.Infinite);
if(queue.Count == 0){ // 再次判断保证已经处理完毕队列中的内容
isSuspend = true;
QueueUtil.writeLine("停止");
}
readerWriterLock.ReleaseWriterLock();
}
}
}).Start();
}
public static void writeLine(string str){
str = string.Format("[{0}]: {1}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), str);
// Console.WriteLine(str);
StreamWriter sw = new StreamWriter("D:\\console.log", true);
sw.WriteLine(str);
sw.Close();
}
}
}