java多執行緒總結六:經典生產者消費者問題實現

一個程式寫手發表於2011-10-28

這是個執行緒同步的經典例子,原始碼如下:

 

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 產品名稱:電話)

相關文章