Когда мы говорим об обработке асинхронных событий с помощью службы Executors, почему при создании нового фиксированного пула потоков используется LinkedBlockingQueue? Приходящие события вообще не зависят друг от друга, так зачем использовать очередь, потому что поток-потребитель все равно будет участвовать в борьбе за получение блокировки? Почему класс Executors не имеет какой-либо гибридной структуры данных (например, параллельной реализации карты), где в большинстве случаев нет необходимости в блокировке?
Исполнители — потребность в LinkedBlockingQueue
Ответы (1)
Есть очень веская причина, по которой исполнитель пула потоков работает с BlockingQueue
(кстати, вы не обязаны использовать реализацию LinkedBlockingQueue, вы можете использовать различные реализации BlockingQueue
). Очередь должна блокироваться, чтобы приостанавливать рабочие потоки, когда нет задач для выполнения. Эта блокировка выполняется с помощью переменных состояния ожидания, поэтому ожидающие рабочие потоки не потребляют ресурсы ЦП, когда очередь пуста.
Если вы используете неблокирующую очередь в пуле потоков, то как рабочие потоки будут опрашивать задачи для выполнения? Им пришлось бы реализовать какой-то опрос, что является лишней тратой ресурсов процессора (будет "занято ожидание").
ОБНОВИТЬ:
Хорошо, теперь я полностью понял вариант использования. Тем не менее вам все равно нужно блокировать сбор. Причина в основном та же - поскольку вы реализуете Producer-Consumer, у вас должны быть средства для рабочих потоков, чтобы они ждали поступления сообщений - и это вы просто не можете сделать без мьютекса + переменной условия (или просто BlockingQueue).
По поводу карты - да, я понимаю, как вы хотите ее использовать, но, к сожалению, такой реализации не предусмотрено. Недавно решал аналогичную задачу: нужно было сгруппировать входящие задачи по некоторым критериям и последовательно выполнять задачи из каждой группы. В результате я реализовал свой собственный GroupThreadPoolExecutor, который выполняет эту группировку. Идея проста: сгруппировать входящие задачи в карту, а затем добавить их в очередь исполнителя, когда завершится предыдущая задача из группы.
Существует большое обсуждение здесь - я думаю, что это имеет отношение к вашему вопросу.