Мой продукт потребитель висит
-
28-09-2019 - |
Вопрос
Пожалуйста, скопируйте программу ниже и попробуйте запустить в своем IDE. Это простое производство потребительской реализации - он работает нормально, когда я использую один производитель и один потребительскую нить, но не удается при использовании 2 каждый. Пожалуйста, дайте мне знать причину, по которой эта программа висит или есть что-то еще не так с ним.
import java.util.LinkedList;
import java.util.Queue;
public class PCQueue {
private volatile Queue<Product> productQueue = new LinkedList<Product>();
public static void main(String[] args) {
PCQueue pc = new PCQueue();
Producer producer = new Producer(pc.productQueue);
Consumer consumer = new Consumer(pc.productQueue);
new Thread(producer, "Producer Thread 1").start();
new Thread(consumer, "Consumer Thread 1").start();
new Thread(producer, "Producer Thread 2").start();
new Thread(consumer, "Consumer Thread 2").start();
}
}
class Producer implements Runnable {
private Queue<Product> queue = null;
private static volatile int refSerialNumber = 0;
public Producer(Queue<Product> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() != null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
queue.add(new Product(++refSerialNumber));
System.out.println("Produced by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ refSerialNumber);
queue.notify();
}
}
}
}
class Consumer implements Runnable {
private Queue<Product> queue = null;
public Consumer(Queue<Product> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() == null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Product product = queue.remove();
System.out.println("Consumed by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ product.getSerialNumber());
queue.notify();
}
}
}
}
class Product {
private int serialNumber;
public Product(int serialNumber) {
this.serialNumber = serialNumber;
}
public int getSerialNumber() {
return serialNumber;
}
}
Решение
Проблема в том, что вы используете Queue.notify (), которая просыпается только одно нить, ожидающее в очереди. Представьте себе продюсер 1 Звонки Notify () и Waight Up Producer 2. Производитель 2 видит, что в очереди есть что-то, чтобы он ничего не производит и просто возвращается к вызов ожидания (). Теперь и ваши производители, и потребители все ожидают, чтобы быть уведомленным, и никто не остается работать, чтобы никого уведомить.
Чтобы решить проблему в вашем коде, используйте Queue.Notifyall (), чтобы просыпаться, каждый поток заблокирован в ожидании (). Это позволит вашим потребителям работать.
Как отмечают, ваша реализация ограничивает очередь, чтобы иметь максимум в нем большего элемента. Таким образом, вы не увидите выгоду от второго набора производителей и потребителей. Для лучшего по всему вокруг реализации я предлагаю вам посмотреть на Блокировка и использовать реализацию, которая может быть ограничена, например, ArrayBlockingQueue.. Отказ Вместо синхронизации и использования ожидания / уведомления, просто используйте Blockingqueue.offer () а также Blockingqueue.take ().
Другие советы
вместо Queue.notify () используйте Queue.notifyall ()