Подождите, пока будет выполнено ровно n работ: производитель, потребитель и счетчик.

Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть поток A, и нужно выполнить n работ. Поток A должен ждать, пока эти n операций не будут полностью выполнены. Моя идея заключается в использовании CountDownLatch со счетом n и использовании шаблона Producer/Consumer для управления Worker.

Я использую AtomicInteger в качестве счетчика: Производитель проверяет, больше ли значение счетчика 0, затем помещает сигнал в BlockingQueue, если значение счетчика меньше или равно 0, Производитель помещает стоп-сигнал в очередь. Потребитель берет из очереди, проверяет, не равен ли сигнал сигналу stopSignal, затем использует ExecutorService для планирования Worker.

Рабочий вызывает getAndDecrement и проверяет, больше ли значение счетчика 0, если да, то выполняет работу, если работа выполнена, то вызывает CountDownLatch#countdown, иначе увеличивает счетчик с помощью incrementAndGet

Проблема в том, что когда работа не выполнена, рабочий должен увеличить счетчик, но это происходит после getAndDecrement, поэтому производитель может увидеть, что значение счетчика равно 0, и поставить сигнал остановки, даже если общее количество работы меньше n!


person robinmag    schedule 21.01.2011    source источник
comment
Разве вы не можете просто запустить ровно n потоков и join() их все? Просто может быть.   -  person 9000    schedule 21.01.2011
comment
я не могу, потому что n может быть большим, скажем тысяча.   -  person robinmag    schedule 21.01.2011


Ответы (1)


Похоже, вы работаете над типичной проблемой производителя/потребителя с некоторой дополнительной сложностью (новое условие ожидания ровно n выполненной работы). Итак, как вы определили, у вас есть производители и потребители. Один производит работу, второй ее потребляет.

Увеличение после создания работы. Уменьшение после того, как работа была потреблена. При таком подходе ваши работники будут пытаться получить из очереди только тогда, когда есть доступная работа.

Теперь, чтобы решить вашу проблему, новое условие ожидания завершения n работ. Если вы ждете завершения определенного количества заданий и четко знаете об этих заданиях, вы можете использовать CyclicBarrier, чтобы остановить поток до тех пор, пока все задания не достигнут барьера.

Обычно существует больше способов координации действий двух рабочих в параллельной ситуации. Производитель/Потребитель не может быть решением этой проблемы, как и Барьер. Я бы порекомендовал посмотреть пакет java.util.concurrent, так как он может пролить больше света на эту тему.

person Kevin Jalbert    schedule 21.01.2011