2

у меня есть следующая ситуация:производитель-потребитель: как знать, сообщить, что prodcution завершена

  1. чтение данные из базы данных
  2. работают «расчет» результат
  3. записи в базу данных

У меня есть поток, который читает из базы данных и помещает сгенерированные объекты в BlockingQueue. Эти объекты чрезвычайно тяжелые, поэтому очередь ограничивает количество объектов в памяти. Несколько потоков берут объекты из очереди, выполняют работу и помещают результаты во вторую очередь. Последний поток принимает результаты второй очереди и сохраняет результат в базе данных.

Проблема в том, как предотвратить взаимоблокировки, например. «потоки вычислений» должны знать, когда больше объектов не будет помещено в очередь. В настоящее время я достигаю этого, передавая ссылки потоков (вызываемых) друг другу и проверяя thread.isDone() перед опросом или предложением, а затем, если элемент имеет значение null. Я также проверяю размер очереди, если в ней есть элементы, они должны быть уничтожены. Использование take или put приводит к взаимоблокировкам.

Есть ли более простой способ достичь этого?

+0

может быть обманом http://stackoverflow.com/questions/5326013/proper-implementation-of-producer-consumer-scenario-and-graceful-termination-of –

ответ

0

Одним из способов достижения было бы поместить сообщение «фиктивное» или «ядовитое» в качестве последнего сообщения в очередь, если вы уверены, что в очередь не поступит больше задач. Например, после помещая сообщение, относящееся к последней строке запроса db. Поэтому производитель помещает фиктивное сообщение в очередь, потребитель, получая это фиктивное сообщение, знает, что в этой партии не ожидается более значимой работы.

+0

То, что у меня больше похоже на производителя-потребителя/образец производителя-потребителя. Средняя часть потребляет данные, а затем передает результат другому потребителю. Дело в том, что у меня есть несколько экземпляров этой «средней части». Это трудная работа. Проблема в том, что «фиктивные данные» могут проходить через эту цепочку быстрее, чем предыдущие «реальные данные», потому что на манекене не делается никакой работы. –

+0

фиктивные данные или сообщение о местоположении были только для того, чтобы избежать ситуации взаимоблокировки; поэтому вы знаете, что больше сообщений не поступит. вы также можете использовать защелку обратного отсчета или что-то, чтобы отслеживать завершение уже запущенных задач. – Scorpion

0

Может быть, вы должны смотреть на CompletionService

Он предназначен для объединения исполнителя и функциональность очереди в одном. Задачи, которые закончили выполнение будет доступна службы заканчивания через

completionServiceInstance.take() 

Вы можете снова использовать другой исполнитель для 3. т.е. заполнить БД с результатами, которые вы будете кормить с результатами, взятых из completionServiceInstance.

+0

Это не помогает мне, потому что я не передаю множество задач, кроме объектов, созданных из базы данных. У меня есть только 3 задачи, которые должны выполняться параллельно. 1. чтение из базы данных. 2. выполнить работу. 3. записать результат в базу данных. Они должны быть параллельны ограничению использования памяти, поскольку чтение и запись намного быстрее, чем фактическая работа. –