Программа Java-производитель-потребитель зависает после «Produced 5» при использовании notify() и еслиJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Программа Java-производитель-потребитель зависает после «Produced 5» при использовании notify() и если

Сообщение Anonymous »

Я изучаю шаблон производитель-потребитель и изначально допустил две ошибки в своей реализации:
  • Я использовал if вместо while< /code>.
  • Я использовал notify вместо notifyAll.
Как в результате я столкнулся со странным поведением со следующим выводом:

Код: Выделить всё

/usr/lib/jvm/temurin-17-jdk-amd64/bin/java -javaagent:/opt/idea/lib/idea_rt.jar=44073:/opt/idea/bin -Dfile.encoding=UTF-8 -classpath /home/xun/Desktop/myworkspace/java-playground/target/classes SharedResource
Produced 0
ConsumerC Consumed 0
Produced 1
ConsumerC Consumed 1
ConsumerA Consumed 1
Produced 2
ConsumerC Consumed 2
ConsumerA Consumed 2
Produced 3
ConsumerC Consumed 3
ConsumerA Consumed 3
Produced 4
ConsumerA Consumed 4
ConsumerC Consumed 4
ConsumerA Consumed 4
ConsumerC Consumed 4
ConsumerA Consumed 4
ConsumerC Consumed 4
ConsumerA Consumed 4
ConsumerC Consumed 4
ConsumerA Consumed 4
Produced 5
После печати Produced 5 программа зависает и больше не печатает никаких сообщений. Это меня смущает, потому что как только поток-производитель выдает значение 5, если в наборе ожидания есть потоки-потребители, один из них должен быть разбужен для использования данных 5, и программа должен продолжить выполнение. Даже если потоки-потребители находятся в списке записей, как только поток-потребитель получит блокировку, программа должна продолжить работу. Я не понимаю, при каких обстоятельствах программа зависает после печати Produced 5.
Проанализируйте причину такого поведения. Ниже мой код:

Код: Выделить всё

public class SharedResource {
private int data;

private boolean available = false;

public synchronized void produce(int value) throws InterruptedException {
while (available) {
wait();
}
data = value;
available = true;
System.out.println("Produced " + value);
//        notifyAll();
notify();
}

public synchronized int consumeWithIf() throws InterruptedException {
if (!available) {
wait();
}

System.out.println(Thread.currentThread().getName() + " Consumed " + data);

available = false;

//        notifyAll();
notify();

return data;

}

public static void main(String[] args) {
SharedResource sharedResource = new SharedResource();

Thread producer = new Thread(new Producer(sharedResource));

Thread consumerA = new Thread(new ConsumerA(sharedResource), "ConsumerA");

Thread consumerC = new Thread(new ConsumerC(sharedResource), "ConsumerC");

producer.start();
consumerA.start();
consumerC.start();

}

}

class Producer implements Runnable {
private SharedResource resource;

public Producer(SharedResource resource) {
this.resource = resource;
}

@Override
public void run() {

for (int i = 0; i < 100; i++) {
try {
resource.produce(i);
//                Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

}
}

class ConsumerA implements Runnable {
private SharedResource resource;

public ConsumerA(SharedResource resource) {
this.resource = resource;
}

@Override
public void run() {

for (int i = 0; i < 100; i++) {
try {
int value = resource.consumeWithIf();
//                Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

}

}
}

class ConsumerC implements Runnable {
private SharedResource resource;

@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
int value = resource.consumeWithIf();
//                Thread.sleep(700);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

}

public ConsumerC(SharedResource resource) {
this.resource = resource;
}
}
Дополнительный контекст
Я понимаю, что использование notifyAll() вместо notify и while вместо if может предотвратить определенные проблемы с синхронизацией. Однако меня особенно смущает, почему программа зависает после печати Produced 5, несмотря на то, что ожидается, что потребительский поток должен использовать созданное значение и позволить программе продолжить работу.


Подробнее здесь: https://stackoverflow.com/questions/793 ... notify-and
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»