從生產者-消費者模型瞭解線程、同步、鎖(java)

代碼主要包括4個類和1個測試類: java

一、Egg 類: 雞蛋,能夠由生產者放入到籃子中,供消費者消費食用。 dom

二、Blanket 類:一個籃子,最多能裝5個雞蛋。 ide

三、Producer 類: 生產者(能夠有1個或多個,但一次只能由一我的放入1個),負責把雞蛋放入到籃子中。 測試

四、Customer 類 :消費者(能夠有1個或多個,但一次只能由一我的吃1個), 會把籃子裏的雞蛋取走食用。 this

五、Tester 類 : 用於測試,可設置多個生產者和消費者。 spa


一、Egg類,有一個ID屬性,用於標識生產和消費的雞蛋是哪個雞蛋,直觀一點: code

public class Egg {
	int id;
	public Egg (int id) {
		this.id = id;
	}
	public String toString () {
		return "雞蛋" + id;
	}
 }



二、Blanket類,其中的放入雞蛋(add)和吃雞蛋(eat)方法使用了同步鎖,即同一時間內只能由一我的操做籃子,放入雞蛋或吃雞蛋: 繼承

public class Blanket {
	int count = 0;
	Egg [] eggs = new Egg[5];

	public synchronized void eat() {
		while(count == 0){
			try{
				this.wait();//當籃子裏雞蛋數目爲0時,等待生產者放入雞蛋
			}catch(InterruptedException ex) {
				ex.printStackTrace();
			}
		}
		this.count--;
		System.out.println(Thread.currentThread().getName() + "吃了"+this.eggs[count].toString());
		this.notifyAll();
	}
	public synchronized void add(Egg e) {
		while(count == 5){
			try {
				this.wait();//當籃子裏有5個雞蛋時,先休息
			}catch(InterruptedException ex){
				ex.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "生產了:" + e.toString());
		this.eggs[count] = e;//生產雞蛋
		count++;
		this.notifyAll();//喚醒消費者
		
	}
}



三、Producer 類,繼承Runable的生產者,在條件容許(籃子雞蛋未滿)的狀況不停的放入雞蛋:
public class Producer implements Runnable{
	Blanket blanket;
	public Producer(Blanket blanket) {
		this.blanket = blanket;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			int i = blanket.count;
			Egg e = new Egg(i);
			blanket.add(e);
			try {
				Thread.sleep((int)(Math.random()*1000));
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}

}



四、Customer 類 ,繼承Runable 的消費者,在籃子裏有雞蛋的時候就會去取出來吃:
public class Customer implements Runnable {
	Blanket blanket;
	public Customer(Blanket blanket) {
		this.blanket = blanket;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			blanket.eat();
			try{
				Thread.sleep((int)(Math.random()*2800));
			}catch(InterruptedException ex){
				ex.printStackTrace();
			}
		}
	}

}



五、Tester 類,用於進行測試,定義一個籃子,和1個或多個生產者,消費者,使這些生產者和消費者共用一個籃子:
public class Tester {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Blanket b = new Blanket();
		Producer p = new Producer(b);
		Producer q = new Producer(b);
		Customer c = new Customer(b);
		Customer d = new Customer(b);
		Customer e = new Customer(b);
		Customer f = new Customer(b);
		new Thread(p,"生產者A").start();
		new Thread(q,"生產者B").start();
		new Thread(c,"消費者A").start();
		new Thread(d,"消費者B").start();
		new Thread(e,"消費者C").start();
		new Thread(f,"消費者D").start();
	}

}



上面的程序運行效果以下:
生產者A生產了:雞蛋0
消費者A吃了雞蛋0
生產者B生產了:雞蛋0
消費者B吃了雞蛋0
生產者A生產了:雞蛋0
消費者D吃了雞蛋0
生產者A生產了:雞蛋0
消費者C吃了雞蛋0
生產者A生產了:雞蛋0
生產者B生產了:雞蛋1
消費者D吃了雞蛋1
生產者B生產了:雞蛋1
生產者A生產了:雞蛋2
生產者A生產了:雞蛋3
生產者A生產了:雞蛋4
消費者B吃了雞蛋4
生產者B生產了:雞蛋5
消費者A吃了雞蛋5
生產者A生產了:雞蛋5
消費者B吃了雞蛋5
它將不停的運行下去,不會出現死鎖。代碼的同步(synchronized)模塊設置在共用的資源(籃子)中,每次只能由一名生產者或者消費者操做籃子,其餘人處於等待(wait)狀態,等它操做完了,它才通知其餘人(notifyAll),其它人則經過競爭,而後只有一個競爭勝利的能夠操做籃子,如此循環。
相關文章
相關標籤/搜索