這是個線程同步的經典例子,源代碼如下:
package demo.thread;
/**
*經典生產者與消費者問題:生產者不斷的往倉庫中存放產品,消費者從倉庫中消費產品。
*其中生產者和消費者都可以有若干個。倉庫容量有限,庫滿時不能存放,庫空時不能取產品
*/
public class ProducersAndConsumers {
public static void main(String[] args) {
Storage storage = new Storage();
Thread consumer = new Thread(new Consumer(storage));
consumer.setName("消費者");
Thread producer = new Thread(new Producer(storage));
producer.setName("生產者");
consumer.start();
producer.start();
}
}
/**
* 消費者
*/
class Consumer implements Runnable {
private Storage storage;
public Consumer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
storage.pop();
}
}
/**
* 生產者
*/
class Producer implements Runnable {
private Storage storage;
public Producer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
Product product = new Product("090505105", "電話");
storage.push(product);
}
}
/**
* 產品類
*/
class Product {
private String id;// 產品id
private String name;// 產品名稱
public Product(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "(產品ID:" + id + " 產品名稱:" + name + ")";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
*倉庫
*/
class Storage {
// 倉庫容量爲10
private Product[] products = new Product[10];
private int top = 0;
// 生產者往倉庫中放入產品
public synchronized void push(Product product) {
while (top == products.length) {
try {
wait();//倉庫已滿,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//把產品放入倉庫
products[top++] = product;
System.out.println(Thread.currentThread().getName() + " 生產了產品"
+ product);
notifyAll();//喚醒等待線程
}
// 消費者從倉庫中取出產品
public synchronized Product pop() {
while (top == 0) {
try {
wait();//倉庫空,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//從倉庫中取產品
--top;
Product p = new Product(products[top].getId(), products[top].getName());
products[top] = null;
System.out.println(Thread.currentThread().getName() + " 消費了產品" + p);
notifyAll();//喚醒等待線程
return p;
}
}
運行結果:
生產者 生產了產品(產品ID:090505105 產品名稱:電話)
消費者 消費了產品(產品ID:090505105 產品名稱:電話)