生產者與消費者問題:
第一步:把架子搭起來
package com.zhj.www;public class ProceduerConsumer {public static void main(String[] args) {}
}//饅頭實體
class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}
//饅頭棧
class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//這個容器只能裝6個饅頭syncStack(int index) {this.index = index;}//往里仍饅頭,之所以使用synchronized關鍵字,是因為防止多個人同時往里扔,public synchronized void push(wotou wt) {arrWT[index] = wt; /*這兩行不能分開index++; */}//從里面取饅頭,拿最上面的那一個public synchronized wotou pop() {index--;return arrWT[index];}}
/*多個生產者,也就是多個線程同時在執行*/
//生產者,用于對饅頭棧的引用,他需要知道生產完饅頭,需要往哪個筐里仍饅頭
class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法對應著生產過程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);}}
}
//消費者
class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println(wotou);}}
}
第二步:
需要考慮當饅頭筐滿了怎么辦?馬上就會報錯?在push方法里考慮,讓這個線程休息一下;
wait方法來源于object;wait的時候這把鎖也就不屬于我了。但是sleep的時候我仍然抓住這把鎖。
package com.zhj.www;import java.io.IOException;public class ProceduerConsumer {public static void main(String[] args) {syncStack ss = new syncStack();proceduer proceduer = new proceduer(ss);consumer consumer = new consumer(ss);new Thread(proceduer).start();new Thread(consumer).start();}
}//饅頭實體
class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}
//饅頭棧
class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//這個容器只能裝6個饅頭//往里仍饅頭,之所以使用synchronized關鍵字,是因為防止多個人同時往里扔,public synchronized void push(wotou wt) {if(index == arrWT.length){try {this.wait();//當前對象正在執行push方法需要wait}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//哪個線程在等待就喚醒哪個線程arrWT[index] = wt; /*這兩行不能分開*/index++; }//從里面取饅頭,拿最上面的那一個public synchronized wotou pop() {if(index == 0) {try {this.wait();}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//object類里的方法,喚醒一個;index--;return arrWT[index];}}
/*多個生產者,也就是多個線程同時在執行*/
//生產者,用于對饅頭棧的引用,他需要知道生產完饅頭,需要往哪個筐里仍饅頭
class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法對應著生產過程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);System.out.println("生產了:"+wt);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
//消費者
class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println("消費了:"+wotou);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
運行過程:
可以發現生產一個饅頭,就消耗一個饅頭。
完善之后的栗子:
package com.zhj.www;import java.io.IOException;public class ProceduerConsumer {public static void main(String[] args) {syncStack ss = new syncStack();proceduer proceduer = new proceduer(ss);consumer consumer = new consumer(ss);new Thread(proceduer).start();new Thread(consumer).start();}
}//饅頭實體
class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}
//饅頭棧
class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//這個容器只能裝6個饅頭//往里仍饅頭,之所以使用synchronized關鍵字,是因為防止多個人同時往里扔,public synchronized void push(wotou wt) {while(index == arrWT.length){try {this.wait();//當前對象正在執行push方法需要wait}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//哪個線程在等待就喚醒哪個線程arrWT[index] = wt; /*這兩行不能分開*/index++; }//從里面取饅頭,拿最上面的那一個public synchronized wotou pop() {while(index == 0) {try {this.wait();}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//object類里的方法,喚醒一個; index--;return arrWT[index];}}
/*多個生產者,也就是多個線程同時在執行*/
//生產者,用于對饅頭棧的引用,他需要知道生產完饅頭,需要往哪個筐里仍饅頭
class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法對應著生產過程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);System.out.println("生產了:"+wt);try {Thread.sleep((int)(Math.random()*200));} catch (InterruptedException e) {e.printStackTrace();}}}
}
//消費者
class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println("消費了:"+wotou);try {Thread.sleep((int)(Math.random()*1000));} catch (InterruptedException e) {e.printStackTrace();}}}
}
運行之后。