Несколько производителей, один потребитель
Мне нужно разработать многопоточное приложение, в котором будет несколько потоков, каждый поток создает собственный журнал событий, который необходимо сохранить в очереди (не Microsoft MSMQ).
Будет другой поток, который считывает данные журнала из очереди и манипулирует ими, с определенной информацией для сохранения информации журнала в файл. В основном здесь мы реализуем парадигму с несколькими производителями, с одним потребителем.
Кто-нибудь может дать предложения о том, как реализовать это в C++ или С#.
Спасибо,
Ответы
Ответ 1
Это очень легко сделать, используя BlockingCollection<T>
, определенный в System.Collections.Concurrent
.
В принципе, вы создаете свою очередь, чтобы все потоки могли получить к ней доступ:
BlockingCollection<LogRecord> LogQueue = new BlockingCollection<LogRecord>();
Каждый производитель добавляет элементы в очередь:
while (!Shutdown)
{
LogRecord rec = CreateLogRecord(); // however that done
LogQueue.Add(rec);
}
И потребитель делает что-то подобное:
while (!Shutdown)
{
LogRecord rec = LogQueue.Take();
// process the record
}
По умолчанию BlockingCollection
использует ConcurrentQueue<T>
в качестве хранилища резервных копий. ConcurrentQueue
выполняет синхронизацию потоков, а BlockingCollection
выполняет ожидание при попытке взять элемент. То есть, если потребитель вызывает Take
, когда в очереди нет элементов, он делает незанятое ожидание (без спящего/вращающегося) до тех пор, пока элемент не будет доступен.
Ответ 2
Вы можете использовать синхронизированную очередь (если у вас есть .NET 3.5 или более старый код) или даже лучше новый ConcurrentQueue<T>
!
Ответ 3
То, что вы планируете, представляет собой классическую очередь потребителей производителей с потоком, потребляющим элементы в очереди, чтобы выполнить некоторую работу. Это может быть завернуто в конструкцию более высокого уровня, называемую "актером" или "активным объектом".
В основном это обертывает очередь и поток, который потребляет элементы в один класс, а остальные - все асинхронные методы в этом классе, которые помещают сообщения в очередь, выполняемые потоком актера. В вашем случае класс может иметь один метод writeData, который хранит данные в очереди и запускает переменную условия, чтобы уведомить поток актора о том, что в очереди есть что-то. Поток актера видит, есть ли какие-либо данные в очереди, если не ждет переменная условия.
Вот хорошая статья о концепции:
http://www.drdobbs.com/go-parallel/article/showArticle.jhtml;jsessionid=UTEXJOTLP0YDNQE1GHPSKH4ATMY32JVN?articleID=225700095
Ответ 4
Несколько производителей, один потребитель - самый простой сценарий для многопоточной передачи очереди. Потоковая очередь может быть реализована как комбинация переменной condition/mutex и std:: queue (добавьте cv, если вы хотите обрабатывать всю очередь).
Пользователь ждет на cv, пока очередь пуста. сигнал производителей при добавлении в очередь (отправка).