Pregunta

Por favor, copiar el programa a continuación y prueba a ejecutar en el IDE. Es una sencilla aplicación Produce Consumidor - funciona muy bien cuando se utiliza un productor y un hilo consumidor, pero falla al utilizar 2 cada uno. Por favor, hágamelo saber la razón por la cual este programa se bloquea o ¿hay algo malo más con ella.

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;
 }
}
¿Fue útil?

Solución

El problema es que está utilizando queue.notify (), que sólo se despierta un solo hilo de espera en la cola. Imaginar productor 1 notifican las llamadas () y se despierta Productor 2. Productor 2 ve que hay algo en la cola para que no se produce nada y simplemente se remonta a la llamada de espera (). Ahora, tanto los productores y los consumidores están a la espera de ser notificado y nadie se quede trabajando para notificar a nadie.

Para resolver el problema en su código, utilice queue.notifyAll () para despertar cada hilo bloqueado en una espera (). Esto permitirá que sus consumidores ejecutar.

Como nota, su aplicación se limita a la cola que tiene como máximo un elemento en ella. Por lo que no verá ningún beneficio del segundo conjunto de productores y consumidores. Para una mejor puesta en práctica todo su alrededor, le sugiero que busque la dirección BlockingQueue y utilizar una implementación que puede ser limitada, por ejemplo, la ArrayBlockingQueue . En lugar de la sincronización y el uso de espera / notificar, basta con utilizar BlockingQueue.offer () y BlockingQueue.take () .

Otros consejos

en lugar de queue.notify () uso queue.notifyAll ()

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top