<span style="font-size:14px;">/**生產者消費者問題,涉及到幾個類
* 第一,這個問題本身就是一個類,即主類
* 第二,既然是生產者、消費者,那麼生產者類和消費者類就是必須的
* 第三,生產什麼,消費什麼,所以物品類是必須的,這裏是饅頭類
* 第四,既然是線程,那麼就不是一對一的,也就是說不是生產一個消費一個,既然這樣,多生產的往哪裏放,
* 現實中就是筐了,在計算機中也就是數據結構,筐在數據結構中最形象的就是棧了,因此還要一個棧類
*/
package thread;
public class ProduceConsume {
public static void main(String[] args) {
SyncStack ss = new SyncStack();//建造一個裝饅頭的框
Producer p = new Producer(ss);//新建一個生產者,使之持有框
Consume c = new Consume(ss);//新建一個消費者,使之持有同一個框
Thread tp = new Thread(p);//新建一個生產者線程
Thread tc = new Thread(c);//新建一個消費者線程
tp.start();//啓動生產者線程
tc.start();//啓動消費者線程
}
}
//饅頭類
class SteamBread{
int id;//饅頭編號
SteamBread(int id){
this.id = id;
}
public String toString(){
return "steamBread:"+id;
}
}
//裝饅頭的框,棧結構
class SyncStack{
int index = 0;
SteamBread[] stb = new SteamBread[6];//構造饅頭數組,相當於饅頭筐,容量是6
//放入框中,相當於入棧
public synchronized void push(SteamBread sb){
while(index==stb.length){//筐滿了,即棧滿,
try {
this.wait();//讓當前線程等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();//喚醒在此對象監視器上等待的單個線程,即消費者線程
stb[index] = sb;
this.index++;
}
//從框中拿出,相當於出棧
public synchronized SteamBread pop(){
while(index==0){//筐空了,即棧空
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();
this.index--;//push第n個之後,this.index++,使棧頂爲n+1,故return之前要減一
return stb[index];
}
}
//生產者類,實現了Runnable接口,以便於構造生產者線程
class Producer implements Runnable{
SyncStack ss = null;
Producer(SyncStack ss){
this.ss = ss;
}
@Override
public void run() {
// 開始生產饅頭
for(int i=0;i<20;i++){
SteamBread stb = new SteamBread(i);
ss.push(stb);
System.out.println("生產了"+stb);
try {
Thread.sleep(10);//每生產一個饅頭,睡覺10毫秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//消費者類,實現了Runnable接口,以便於構造消費者線程
class Consume implements Runnable{
SyncStack ss = null;
public Consume(SyncStack ss) {
super();
this.ss = ss;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){//開始消費饅頭
SteamBread stb = ss.pop();
System.out.println("消費了"+stb);
try {
Thread.sleep(100);//每消費一個饅頭,睡覺100毫秒。即生產多個,消費一個
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}</span>
運行結果: