java_Thread生產消費者問題

生產消費者問題是經典的問題
我有一個箱子,可以放蘋果,有一個生產者生產蘋果,一個消費者消費蘋果,用線程可以這樣寫:

/*箱子*/
class PT {
    private String info="蘋果";

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

}

/*生產者*/
class MyThread9 implements Runnable {

    private PT pt;
    public MyThread9(PT pt) {
        this.pt = pt;
    }
    @Override
    public void run() {
        for(int i = 0; i<10; i++) {
            System.out.println("生產:蘋果");
            pt.setInfo("蘋果");
        }

    }   
}

/*消費者*/
class MyThread10 implements Runnable {

    private PT pt;
    public MyThread10(PT pt) {
        this.pt = pt;
    }
    @Override
    public void run() {
        for(int i = 0; i<10; i++) {
            System.out.println("消費:" + pt.getInfo());
        }   
    }   
}

public class test5 {

    public static void main(String ar[]) {
        PT pt = new PT();
        MyThread9 m = new MyThread9(pt);
        MyThread10 m1 = new MyThread10(pt);
        Thread t1 = new Thread(m,"生產者");
        Thread t2 = new Thread(m1,"消費者");
        t1.start();
        t2.start();
    }
}

而這樣的結果,會出問題,如果我的箱子只能放一個蘋果,那麼就只有
箱子爲空,生產者才能放蘋果,
箱子不爲空,消費者才能取蘋果
而程序運行的結果:
這裏寫圖片描述
會出現一直放,或者一直取,這樣明顯不符合邏輯。

要解決這個問題,需要用到Object類的方法:
這裏寫圖片描述
這裏寫圖片描述
例子:

/*箱子*/
class PT {
    private String info="蘋果";

    /*箱子爲空的標記*/
    private boolean flag = false;

    public synchronized void get() {

        if(flag) {
            /*箱子爲空,當前線程等待,等到箱子不爲空時會被喚醒*/
            try {
                super.wait();

            } catch(Exception e) {e.printStackTrace();}

        } else {

        /*箱子不爲空,取走蘋果*/
        System.out.println("消費:"+info);

        /*標記箱子爲空*/
        flag = true;

        /*喚醒線程*/
        super.notify();
        }
    }

    public synchronized void setInfo(String info) {

        if(!flag) {
            /*如果箱子不爲空,則生產者線程等待,等待箱子爲空的時候會被喚醒*/
            try {
                super.wait();
            } catch(Exception e){e.printStackTrace();}
        }

        else {
            /*箱子爲空,可以生產*/
            this.info = info;
            System.out.println("生產:蘋果");

            /*標記箱子不爲空*/
            flag = false;

            /*喚醒等待的線程*/
            super.notify();
        }

    }

}

/*生產者*/
class MyThread9 implements Runnable {

    private PT pt;
    public MyThread9(PT pt) {
        this.pt = pt;
    }
    @Override
    public void run() {
        for(int i = 0; i<10; i++) {
            pt.setInfo("蘋果");
        }

    }   
}

/*消費者*/
class MyThread10 implements Runnable {

    private PT pt;
    public MyThread10(PT pt) {
        this.pt = pt;
    }
    @Override
    public void run() {
        for(int i = 0; i<10; i++) {
            pt.get();
        }   
    }   
}

public class test5 {

    public static void main(String ar[]) {
        PT pt = new PT();
        MyThread9 m = new MyThread9(pt);
        MyThread10 m1 = new MyThread10(pt);
        Thread t1 = new Thread(m,"生產者");
        Thread t2 = new Thread(m1,"消費者");
        t2.start();
        t1.start();

    }
}

結果:
這裏寫圖片描述
這樣就能解決生產者消費者問題
至於notify()與notifyAll()的區別,你可以理解爲,
notify()是有序的喚醒,
notifyAll()是無序的喚醒,喚醒後誰的優先級高,誰就更有可能先執行。

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