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

 

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