Лидер / Последователь - это эффективная работа с несколькими работниками.Когда у вас нет работы (рабочих мест), чем занят ваш работник или рабочие?Обычный простой подход заключается в том, чтобы создавать рабочие задания для одного потока потребителя, либо путем создания потока, либо с помощью пула потоков.Обсуждаемый шаблон обеспечивает альтернативный подход, позволяющий избежать синхронизации между диспетчером и работником, поскольку поток (лидер), который получает задание, выполняет саму задачу.Это продвигает ожидающего работника на позицию лидера, чтобы поддерживать отзывчивость системы.
Имейте в виду, что в этой статье обсуждаются низкоуровневые механизмы ожидания работы, которые не (легко) поддерживают несколько потоков, ожидающих одну и ту же «очередь» работы.Конструкции более высокого уровня, такие как очереди сообщений, которые поддерживают несколько рабочих потоков, все из которых выполняют блокирующее чтение в одном и том же источнике (конкурирующие потребители AKA), могут не получить описанного преимущества.Более высокий уровень абстракции обеспечивает большую простоту программирования, но, как правило, за счет производительности, которая может быть достигнута при более низкоуровневом подходе.
EDIT1:
Вот подготовленный образец (только псевдокод).Обратите внимание, что я не писал статью и не проверял ее, поэтому я не могу по-настоящему говорить о производительности одного против другого.Но, надеюсь, это показывает разницу в стиле.
// in QueueHandler processing loop
while(true)
{
// read, blocking until one arrives
Request req = requestQueue.BlockingRead();
// we have a unit of work now but the QueueHandler should not process it
// because if it is long running then no new requests can be handled.
// so we spawn / dispatch to a thread
ThreadPool.QueueWorkItem(req);
// or new Thread(DoWork(), req).Start;
// at this point we know that the request will get picked up in
// an unknown but hopefully very short amount of time by a
// waiting (sleeping/blocking) or new thread and it will get passed the
// work. But doing so required the use of thread synchronization
// primitives that can cause all processors to flush their caches
// and other expensive stuff.
} // now loop back up to read the next request
VS
// in Leader
while(true)
{
// I'm the leader, blocking read until a request arrives
Request req = queue.BlockingRead();
// We have a unit of work and we are going to process it ourselves.
// But first we notify a follower.
Followers.PromoteOne();
// work on the request in this thread!
DoWorkOn(req);
// now that I'm done, wait to the the leader
Followers.BlockingWaitToBeLeader();
}