多个生产者,单个消费者

时间:2011-02-24 13:37:36

标签: c# c++ multithreading producer-consumer

我必须开发一个多线程应用程序,其中会有多个线程,每个线程生成自定义事件日志,需要保存在队列中保存(不是微软MSMQ)。

将会有另一个线程从队列中读取日志数据并使用某些信息对其进行操作,以将日志信息保存到文件中。基本上,我们在这里实现了多个生产者单个消费者范例。

任何机构都可以建议我如何在C ++或C#中实现它。

谢谢,

4 个答案:

答案 0 :(得分:9)

使用BlockingCollection<T>中定义的System.Collections.Concurrent非常容易做到这一点。

基本上,您创建队列以便所有线程都可以访问它:

BlockingCollection<LogRecord> LogQueue = new BlockingCollection<LogRecord>();

每个生产者都将项目添加到队列中:

while (!Shutdown)
{
    LogRecord rec = CreateLogRecord(); // however that's done
    LogQueue.Add(rec);
}

消费者做了类似的事情:

while (!Shutdown)
{
    LogRecord rec = LogQueue.Take();
    // process the record
}

默认情况下,BlockingCollection使用ConcurrentQueue<T>作为后备存储。 ConcurrentQueue负责线程同步,并且BlockingCollection在尝试获取项目时执行非忙等待。也就是说,如果消费者在队列中没有项目时调用Take,则会在项目可用之前执行非忙碌等待(无休眠/旋转)。

答案 1 :(得分:2)

您可以使用synchronized queue(如果您使用的是.NET 3.5或更早的代码),或者更好地使用新的ConcurrentQueue<T>

答案 2 :(得分:2)

您计划的是一个经典的生产者消费者队列,其中一个线程消耗队列中的项目来完成某些工作。这可以包含在一个称为“actor”或“active object”的更高级别的构造中。

基本上,这会将队列和使用项目的线程包装到单个类中,其他线程将此类上的所有异步方法都放在队列中的消息上,由actor的线程执行。在您的情况下,类可以有一个方法writeData,它将数据存储在队列中,并触发条件变量以通知actor线程队列中有什么东西。如果不等待条件变量,则actor线程会查看队列中是否有任何数据。

这是一篇关于这个概念的好文章:

http://www.drdobbs.com/go-parallel/article/showArticle.jhtml;jsessionid=UTEXJOTLP0YDNQE1GHPSKH4ATMY32JVN?articleID=225700095

答案 3 :(得分:1)

多个生产者,单个消费者是多线程队列通信最简单的方案。线程队列可以实现为条件变量/互斥体和std :: queue的组合(如果要处理队列已满,则添加cv)。

当队列为空时,消费者在cv上等待。生成器在添加到队列(发送)时发出信号。