Производитель / Потребитель, использующий ожидание и уведомление
Я пытаюсь согласовать проблему с продюсером и потребителем. Производитель ставит в очередь 10 объектов. То есть метод запуска продюсера включает в себя простой цикл для добавления 10 объектов, после чего он завершается. Когда очередь заполнена (размер очереди 10), в методе добавления очереди вызывается wait() - >. На стороне потребителя потребитель начинает с того, что смотрит на объекты, а затем начинает их удалять. Проблема, с которой я столкнулся, заключается в том, что примерно в 50% случаев, когда программа запускается, вывод завершается после того, как производитель помещает 10 объектов в очередь. Остальные 50% случаев программа работает нормально, то есть потребитель снимает все объекты. Моим предыдущим решением этой проблемы было создание нового потребительского потока в методе запуска производителя. Поэтому, как только производитель поместил десять объектов в очередь, был создан новый потребительский поток, и я использовал join() для синхронизации операций. Однако я хотел бы заставить процесс работать с ожиданием и уведомлением. Может кто-нибудь посоветовать, пожалуйста, что я делаю не так? Спасибо
@Override
public synchronized boolean add(Process element) {
if(isFull())
{
waitForNotify();
}
else
{
queue.add(element);
}
return true;
}
private void invokeNotify() {
try {
notify();
} catch (Exception e) {
e.printStackTrace();
}
}
private void waitForNotify() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public synchronized boolean offer(Process element) throws IllegalStateException {
queue.add(element);
this.queue = newHeapSort.heapify(queue, queue.size());
return true;
}
@Override
public synchronized Process peek() {
if(queue.isEmpty())
{
waitForNotify();
}
return(queue.get(0));
}
@Override
public synchronized Process head() {
if(queue.isEmpty())
{
invokeNotify();
}
Process head = queue.get(0);
queue.remove(0);
return head;
}
1 ответ
Производитель никогда не уведомляет потребительскую ветку. Поэтому, если потребитель запускается первым, он находит очередь пустой и ждет вечно.
Я бы просто использовал BlockingQueue, который сделает это за вас.
Если вы действительно хотите использовать wait()
а также notify()
Вам необходимо:
- использовать петлю вокруг вашего
wait()
звонки и возврат в состояние ожидания, если условие для пробуждения не соответствует действительности - решить, когда производитель должен уведомить (обычно, когда он помещает элемент в очередь)
- decide when the consumer should notify (normally, when it removes an item from the queue)
- decide when the consumer should wait (normally, when the queue is empty)
- decide when the producer should wait (normally, when the queue is full)
- stop ignoring InterruptedException. Just let them propagate.
я хотел бы использовать notifyAll()
, which would also make sure that everything works well if there are several producers or consumers.