多線程專題-生產者消費者問題

等待喚醒機制其實就是經典的“生產者與消費者”的問題。
就拿生產包子消費包子來說等待喚醒機制如何有效利用資源:

包子鋪線程生產包子,吃貨線程消費包子。當包子沒有時(包子狀態爲false),吃貨線程等待,包子鋪線程生產包子(即包子狀態爲true),並通知吃貨線程(解除吃貨的等待狀態),因爲已經有包子了,那麼包子鋪線程進入等待狀態。接下來,吃貨線程能否進一步執行則取決於鎖的獲取情況。如果吃貨獲取到鎖,那麼就執行吃包子動作,包子吃完(包子狀態爲false),並通知包子鋪線程(解除包子鋪的等待狀態),吃貨線程進入等待。包子鋪線程能否進一步執行則取決於鎖的獲取情況。

代碼演示:

包子資源類

public class BaoZi {

    String  pier ;
    String  xianer ;
    boolean  flag = false ;//包子資源 是否存在  包子資源狀態
}

吃貨線程類

public class ChiHuo extends Thread {

    private BaoZi bz;

    public ChiHuo(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        synchronized (bz) {
            while (true) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (bz.flag == false) {//沒包子
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("吃貨正在吃" + bz.pier + bz.xianer + "包子");
                bz.flag = false;
                bz.notify();
            }
        }
    }
}

包子鋪線程類:

public class BaoZiPu extends Thread {

    private BaoZi bz;

    public BaoZiPu(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0;
        //同步
        synchronized (bz) {
            //造包子
            while (true) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (bz.flag == true) {//包子資源  存在
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 沒有包子  造包子
                System.out.println("包子鋪開始做包子");
                if (count % 2 == 0) {
                    // 冰皮  五仁
                    bz.pier = "冰皮";
                    bz.xianer = "五仁";
                } else {
                    // 薄皮  牛肉大蔥
                    bz.pier = "薄皮";
                    bz.xianer = "牛肉大蔥";
                }
                count++;
                bz.flag = true;
                System.out.println("包子造好了:" + bz.pier + bz.xianer);
                System.out.println("吃貨來吃吧");
                //喚醒等待線程 (吃貨)
                bz.notify();
            }
        }
    }
}

測試類:

public class Test {

    public static void main(String[] args) {
        //等待喚醒案例
        BaoZi bz = new BaoZi();

        ChiHuo ch = new ChiHuo(bz);
        ch.setName("吃貨");

        BaoZiPu bzp = new BaoZiPu(bz);
        bzp.setName("包子鋪");

        ch.start();
        bzp.start();
    }
}

執行效果:

包子鋪開始做包子
包子造好了:冰皮五仁
吃貨來吃吧
吃貨正在吃冰皮五仁包子
包子鋪開始做包子
包子造好了:薄皮牛肉大蔥
吃貨來吃吧
吃貨正在吃薄皮牛肉大蔥包子
包子鋪開始做包子
包子造好了:冰皮五仁
吃貨來吃吧
吃貨正在吃冰皮五仁包子
包子鋪開始做包子
包子造好了:薄皮牛肉大蔥
吃貨來吃吧
吃貨正在吃薄皮牛肉大蔥包子
包子鋪開始做包子
包子造好了:冰皮五仁
吃貨來吃吧
吃貨正在吃冰皮五仁包子
包子鋪開始做包子
包子造好了:薄皮牛肉大蔥
吃貨來吃吧
吃貨正在吃薄皮牛肉大蔥包子
包子鋪開始做包子
包子造好了:冰皮五仁
吃貨來吃吧
吃貨正在吃冰皮五仁包子
包子鋪開始做包子
包子造好了:薄皮牛肉大蔥
吃貨來吃吧

Process finished with exit code -1

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