1. 程式人生 > >多執行緒之生產者消費者

多執行緒之生產者消費者

/*
 * 以生產饅頭,消耗饅頭為例
 */
public class ProduceConsume {  
  
    public static void main(String[] args) {  
        SyncStack ss = new SyncStack();//建造一個裝饅頭的框  
        Producer p = new Producer(ss);//新建一個生產者,使之持有框  
        Consume c = new Consume(ss);//新建一個消費者,使之持有同一個框  
         new Thread(p).start();//新建一個生產者執行緒並啟動  
         try {
			Thread.sleep(1000);//造成一個生產執行緒和消費執行緒的時間差,就不會產生沒生產就消費的情況
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
         new Thread(c).start();;//新建一個消費者執行緒並啟動    
    }  
  
}  
  
//饅頭類  
class SteamBread{  
    int id;//饅頭編號  
    SteamBread(int id){  
        this.id = id;  
    }  
    public String toString(){  //重寫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) {  
                e.printStackTrace();  
            }  
        }  
        this.notify();//喚醒在此物件監視器上等待的單個執行緒,即消費者執行緒  
        stb[index] = sb;  
        index++;  
    }  
      
    //從框中拿出,相當於出棧  
    public synchronized SteamBread pop(){  
        while(index==0){//筐空了,即棧空  
            try {  
                this.wait();  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
        this.notify();  
        index--;//push第n個之後,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<10;i++){  
            SteamBread stb = new SteamBread(i);  
            ss.push(stb);  
           System.out.println("生產了"+stb);  
            try {  
                Thread.sleep((int)(Math.random()*1000));//每生產一個饅頭,睡覺隨機秒  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  
  
//消費者類,實現了Runnable介面,以便於構造消費者執行緒  
class Consume implements Runnable{  
    SyncStack ss = null;  
    public Consume(SyncStack ss) {  
        this.ss = ss;  
    }  
    @Override  
    public void run() {  
        for(int i=0;i<10;i++){//開始消費饅頭  
            SteamBread stb = ss.pop();  
            System.out.println("消費了"+stb);  
            try {  
                Thread.sleep((int)(Math.random()*1000));//每消費一個饅頭,睡覺隨機秒。 
            } catch (InterruptedException e) {   
                e.printStackTrace();  
            }  
        }  
    }     
}