java多線程之生產者消費者經典問題 - 很不錯的範例

<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>  

運行結果:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章