1. 程式人生 > >Java 經典例題:生產者/消費者問題

Java 經典例題:生產者/消費者問題

Java 經典例題:生產者/消費者問題

1. 問題

  1. 生產者(Productor)將產品交給店員(Clerk),而消費者(Customer)從店員處取走產品,店員一次只能持有固定數量的產品(比如:20),如果生產者試圖生產更多的產品,店員會叫生產者停一下,如果店中有空位放產品了再通知生產者繼續生產;如果店中沒有產品了,店員會告訴消費者等一下,如果店中有產品了再通知消費者來取走產品。

2.分析

  1. 是否涉及到多執行緒的問題?
    生產者、消費者
  2. 是否涉及到共享資料?
    有!需考慮執行緒的安全
  3. 此共享資料為?
    及為產品的數量
  4. 是否涉及到執行緒的通訊?
    存在,生產者與消費者的通訊

3.demo

class Clerk{//店員
	int product;//共享資料
	
	public synchronized void addProduct() {//生產產品
		if(product >=20) {
			try {
				wait();//掛起執行緒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else {
			product++;
			System.out.println(Thread.currentThread().getName()+":生產了第"+product+"產品");
			notify();//既然已經產品大於0小於20了,那個就喚醒消費者的執行緒
		}
	}
	public synchronized void consumeProduct() {//消費產品
		if(product <=0) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println(Thread.currentThread().getName()+":消費了第"+product+"產品");
			product--;
			notify();
		}
	}
}
class Producer implements Runnable{//生產者
	Clerk clerk;
	public Producer(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run () {//搶到資源執行的方法
		System.out.println("生產者開始生產產品");
		while(true) {
			try {
				Thread.currentThread().sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.addProduct();
		}
	}
}
class Consumer implements Runnable{
	Clerk clerk;
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run() {//搶到資源執行的方法
		System.out.println("消費者開始消費產品");
		while(true) {
			try {
				Thread.currentThread().sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.consumeProduct();
		}
	}
}
public class TestProduceConsume {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Producer p1 = new Producer(clerk);
		Consumer c1 = new Consumer(clerk);
		Thread t1 = new Thread(p1);//一個生產者的執行緒
		Thread t3 = new Thread(p1);//一個生產者的執行緒
		Thread t2 = new Thread(c1);//一個消費者的執行緒
		t1.setName("生產者1");
		t3.setName("生產者2");
		t2.setName("消費者2");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
  1. 輸出
    輸出