2010-06-18 45 views
2

請複製下面的程序並嘗試在IDE中運行。這是一個簡單的Produce Consumer實現 - 當我使用一個Producer和一個Consumer線程時它運行良好,但每次使用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; 
} 
} 

回答

4

的問題是,你正在使用queue.notify(),這將只喚醒一個線程等待隊列。想象生產者1調用notify()並喚醒生產者2.生產者2發現隊列中有東西,所以他不產生任何東西並簡單地返回到wait()調用。現在,您的生產者和消費者都在等待通知,沒有人留下工作通知任何人。

要解決代碼中的問題,請使用queue.notifyAll()喚醒在wait()處阻塞的每個線程。這將允許您的消費者運行。

作爲說明,您的實施將隊列限制爲最多隻有一個項目。所以你不會看到第二組生產者和消費者帶來的好處。爲了更好地實現,我建議你看看BlockingQueue並使用可以有界的實現,例如ArrayBlockingQueue。而不是同步和使用等待/通知,只需使用BlockingQueue.offer()BlockingQueue.take()

+0

哎呀..傻我..終於我得到使用notifyAll().. 非常感謝! – haps10 2010-06-18 08:02:31

1

代替queue.notify()使用queue.notifyAll()

+0

非常感謝!!!!! – haps10 2010-06-18 08:02:57