1.11 等待通知機制wait和notify的使用,簡單的生產者消費者

能夠運行的代碼,簡單的生產者和消費者代碼

備註:我自己寫的時候,總是把在不同的對象上面調用,所以導致一直報錯,下面會有報錯代碼

1)通過synchronized獲取對象的鎖,一定要有synchronized同步中wait和notify

2)如果條件不滿足,那麼調用對象的wait()方法,被通知後仍要檢查條件。

3)條件滿足則執行對應的邏輯。

while(true)
    synchronized (對象){
        //如果倉庫滿了,就讓他等待消費
        while(條件不滿足){
            對象.wait();
        }
        //處理自己的邏輯
        DoSomeThing();
        //喚醒在對象上等待的其他線程
        對象.notifyAll();
    }
}
package cn.enjoyedu.ch1.wn;

/**
 * @author: honry.guan
 * @create: 2020-06-09 23:06
 **/
public class TestBroad {
    private Integer sum;

    public TestBroad(Integer sum) {
        this.sum = sum;
        System.out.println("初始麪包:"+sum);
    }

    static class Product extends Thread{
        private TestBroad testBroad;

        public Product(TestBroad testBroad,String name) {
            super(name);
            this.testBroad = testBroad;
        }

        @Override
        public void run() {
            try {
                while(true){
                    synchronized (testBroad){
                        //如果倉庫滿了,就讓他等待消費
                        while(testBroad.sum >= 20){
                            System.out.println("當前庫存滿了,等待消費:"+testBroad.sum);
                            testBroad.wait();
                        }
                        //庫存還沒有滿,新增庫存,並且喚醒所有的消費者和生產者
                        testBroad.sum = testBroad.sum +1;
                        System.out.println("生產者生產了一個麪包:"+testBroad.sum);
                        testBroad.notifyAll();
                    }

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class Customer extends Thread{
        private TestBroad testBroad;

        public Customer(TestBroad testBroad,String name) {
            super(name);
            this.testBroad = testBroad;
        }
        @Override
        public void run() {
            try {
                while(true){
                    synchronized (testBroad) {
                        System.out.println(Thread.currentThread().getName());

                        while (testBroad.sum <= 0) {
                            System.out.println("當前庫存不足,等待生產:" + testBroad.sum);

                            testBroad.wait();
                        }
                        //當有足夠的庫存的時候,喚醒所有生產者和消費者
                        testBroad.sum = testBroad.sum - 1;
                        System.out.println("消費者吃了一個麪包:" + testBroad.sum);
                        testBroad.notifyAll();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TestBroad testBroad = new TestBroad(10);
        Integer sum = 10;
        for (int i = 0; i < 3; i++) {
            new Product(testBroad,"生產者-"+i).start();
            new Customer(testBroad,"消費者-"+i).start();
        }
    }
}

運行結果

初始麪包:10
生產者生產了一個麪包:11
生產者生產了一個麪包:12
生產者生產了一個麪包:13
生產者生產了一個麪包:14
生產者生產了一個麪包:15
生產者生產了一個麪包:16
生產者生產了一個麪包:17
生產者生產了一個麪包:18
生產者生產了一個麪包:19
生產者生產了一個麪包:20
當前庫存滿了,等待消費:20
消費者吃了一個麪包:19
生產者生產了一個麪包:20

錯誤的加鎖導致的報錯

對integer加鎖導致錯誤,在執行sum = sum - 1;,sum對象已經發生了改變,不再是原來的對象了,所以會報錯

package cn.enjoyedu.ch1.wn;

/**
 * @author: honry.guan
 * @create: 2020-06-09 23:06
 **/
public class TestBroad2 {
    private Integer sum;

    public TestBroad2(Integer sum) {
        this.sum = sum;
        System.out.println("初始麪包:"+sum);
    }

    static class Product extends Thread{
        private Integer sum;

        public Product(Integer sum,String name) {
            super(name);
            this.sum = sum;
        }

        @Override
        public void run() {
            try {
                while(true){
                    synchronized (sum){
                        System.out.println("------"+Thread.currentThread().getName()+"===="+sum.hashCode());
                        System.out.println(sum.hashCode());
                        //如果倉庫滿了,就讓他等待消費
                        while(sum >= 20){
                            System.out.println("當前庫存滿了,等待消費:"+sum);
                            sum.wait();
                        }
                        //庫存還沒有滿,新增庫存,並且喚醒所有的消費者和生產者
                        sum = sum +1;
                        System.out.println("生產者生產了一個麪包:"+sum);
                        sum.notifyAll();
                    }

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class Customer extends Thread{
        private Integer sum;

        public Customer(Integer sum,String name) {
            super(name);
            this.sum = sum;
        }
        @Override
        public void run() {
            try {
                while(true){
                    synchronized (sum) {
                        System.out.println("------"+Thread.currentThread().getName()+"===="+sum.hashCode());
                        while (sum <= 0) {
                            System.out.println("當前庫存不足,等待生產:" + sum);

                            sum.wait();
                        }
                        //當有足夠的庫存的時候,喚醒所有生產者和消費者
                        sum = sum - 1;
                        System.out.println("消費者吃了一個麪包:" + sum);
                        sum.notifyAll();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TestBroad2 testBroad = new TestBroad2(10);
        Integer sum = 10;
        for (int i = 0; i < 3; i++) {
            new Product(sum,"生產者-"+i).start();
            new Customer(sum,"消費者-"+i).start();
        }
    }
}

報錯:解決方法就是用第一個demo,把integer對象包裝起來

初始麪包:10
------生產者-0====10
10
生產者生產了一個麪包:11
Exception in thread "生產者-0" ------消費者-0====10
消費者吃了一個麪包:9
java.lang.IllegalMonitorStateException
------生產者-1====10
	at java.lang.Object.notifyAll(Native Method)
	at cn.enjoyedu.ch1.wn.TestBroad2$Product.run(TestBroad2.java:38)
Exception in thread "消費者-0" 10
生產者生產了一個麪包:11
java.lang.IllegalMonitorStateException

 

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