Frage

Bitte kopieren Sie das Programm, und versuchen Sie in Ihrem IDE ausgeführt wird. Es ist eine einfache Produce Consumer Umsetzung - es gut läuft, wenn ich einen Produzenten und einen Consumer-Thread verwenden, aber schlägt fehl, wenn je 2 verwendet wird. Bitte teilen Sie mir den Grund, warum dieses Programm hängt oder sonst noch etwas daran zu beanstanden ist.

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;
 }
}
War es hilfreich?

Lösung

Das Problem ist, dass Sie verwenden queue.notify (), die nur einen einzigen Thread oben wartet auf die Queue aufwachen wird. Stellen Sie sich vor Producer 1 Anrufe notify () und aufwacht Produzent 2. Produzent 2 sieht, dass es etwas in der Warteschlange ist so er nichts produzieren und einfach geht zurück auf die Wartezeit () -Aufruf. Nun sind beide Ihre Produzenten und Verbraucher sind alle Warte benachrichtigt zu werden, und niemand links arbeitet jemand zu informieren.

Um das Problem in Ihrem Code zu lösen, verwenden queue.notifyAll () jedes Thema in einem Warte blockiert aufzuwachen (). Dies ermöglicht es Ihren Kunden zu laufen.

Als Hinweis, schränkt die Implementierung der Warteschlange höchstens ein Element darin zu haben. So werden Sie keinen Nutzen aus dem zweiten Satz von Produzenten und Konsumenten sehen. Für eine bessere rundum Implementierung, ich schlage vor, Sie schauen auf ArrayBlockingQueue . Statt synchronisieren und mit Warte / benachrichtigen, verwenden Sie einfach BlockingQueue.offer () und BlockingQueue.take () .

Andere Tipps

statt queue.notify () Verwendung queue.notifyAll ()

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top