В Java невозможно определить, когда несколько производителей / потребителей завершили работу.

Есть несколько производителей потребительских шаблонов производитель1 -> потребитель1 / производитель2 -> потребитель2 / производитель 3, каждый производитель использует службу завершения, но у меня возникают проблемы с кодированием логики для разработки, когда она завершена.

Проблема в том, что main помещает некоторые (x) задач в очередь производителя 1, это, в свою очередь, заставит производитель 1 поставить (y) задач на производителя 2, а производитель 2 поместит z задач на производителя 3. x, y и z равны разные, поэтому main не может просто смотреть на очередь завершения производителя 3 и брать фьючерсы z, потому что main не знает z.

Итак, я попробовал идею ядовитой таблетки вместе с CountDownLatch, инициализированным до 3, главный знает, что у производителя 1 есть только x задач, поэтому я могу отправить ядовитую таблетку в конце, а затем, когда производитель 1 получит ее, он может уменьшить защелку и отправить яд pill производителю 2, а производитель 2 получает единицу, он уменьшает защелку, отправляемую производителю 3. Когда производитель 3 принимает ее, он уменьшает защелку. main просто выполняет countdownlatch.await () и не сможет продолжить, пока все задачи не будут выполнены. Но это работает только в том случае, если каждая служба-исполнитель ограничена одним потоком, потому что, когда ядовитая таблетка получена производителем, это означает, что все предыдущие задачи были запущены, а не завершены.

Итак, как мне обойти это, я думаю, что где-то мне не хватает более простого решения.


person Paul Taylor    schedule 14.11.2011    source источник
comment
Можете ли вы дать нам код в виде ваших типов? Все ли производители генерируют один и тот же тип вывода?   -  person hellectronic    schedule 14.11.2011
comment
@ user294896: Я довольно регулярно использую отравляющие таблетки, но я не уверен, что понимаю, что вы имеете в виду под ... потому что, когда отравленная таблетка получена производителем, это означает, что все предыдущие задачи были запущены ... Ядовитую таблетку должен получить потребитель (а не производитель), а затем действовать соответствующим образом: например, уменьшив защелку и / или создав нового производителя (если я правильно понял ваш пример). Но в любом случае: вы должны решить, что вы будете делать, когда употребляете таблетку. Простое производство отравленной таблетки не должно иметь никакого эффекта. Можете немного уточнить?   -  person TacticalCoder    schedule 14.11.2011
comment
@ user29489 Когда я говорю, что получено производителем, это потому, что класс является производителем И потребителем. Итак, этот класс получает работу, а после ее завершения передает новую работу другому типу производителя / потребителя.   -  person Paul Taylor    schedule 14.11.2011
comment
@ user294896: так, если я правильно понимаю, вы уменьшаете уникальную защелку для всех ваших разных классов производителя и потребителя [i]? Если это так, очевидно, что это не сработает, если у вас несколько потоков: вам понадобится как минимум 3 пилюли для каждого потока, который вы хотите запускать параллельно. Но в любом случае я не уверен, что понимаю, что вы хотите сделать: хотите ли вы, чтобы все ваши, скажем, параллели consumer2 / maker3 начали свою работу одновременно (т.е. когда все consumer1 / продюсер2 < / i> закончили потребление)? Дело в том, что вы не обязаны всегда использовать одни и те же таблетки: это могут быть таблетки производителя, таблетки для потребителей и т. Д.   -  person TacticalCoder    schedule 14.11.2011
comment
@ user294896, вы слишком усложняете то, что я говорю, но это не имеет значения, потому что у меня все равно есть правильный ответ, спасибо.   -  person Paul Taylor    schedule 15.11.2011


Ответы (1)


Вы можете выключить и дождаться завершения каждой службы исполнителя по очереди.

ExecutorService[] services = { executor1, executor2, executor3 };
for(ExecutorService service: services) {
    service.shutdown();
    service.awaitTermination(1, TimeUnit.MINUTES);
}
person Peter Lawrey    schedule 14.11.2011
comment
Таким образом, он завершает работу, как только задача отправляется производителю 1, awaitTermination () не вернется, пока производитель 1 не завершит работу, и в этот момент безопасно выполнить shutdown () для производителя 2, потому что он получит все свои задачи, и мне не нужны ядовитые таблетки, защелка или даже служба завершения, большое спасибо, я попробую сейчас. - person Paul Taylor; 14.11.2011
comment
Да, мне следовало включить объяснение. Завершение работы предотвращает новые задачи, и служба прекращает работу, когда все задачи завершены. - person Peter Lawrey; 14.11.2011