美文网首页
生产者消费者模式-wait/notify实现

生产者消费者模式-wait/notify实现

作者: 飞奔吧牛牛 | 来源:发表于2019-11-18 00:12 被阅读0次

    假设一个线程生产数据,放入仓库中,另一个线程从仓库中取出数据来消费。仓库,可以存储一些数据,容量为maxSize,有两个操作,put()存和take()取。要求,当存数据时,如果仓库已经达到最大存储数量maxSize,则进入等待状态,有人唤醒它时,继续存,每存储一次数据,通知其他线程去取。同理当取数据时,如果仓库中存储数量为0,则进入等待状态,有人唤醒它时,继续取,每取出一次数据,通知其他线程去生产。

    封装仓库
    
    class EventStorage {
        private int maxSize;
        private LinkedList<Object> storage;
    
        public EventStorage() {
            maxSize = 10;
            storage = new LinkedList<>();
        }
    
        /**
         * 添加,满了就进入等待状态,等待别人唤醒后再继续添加
         * 每添加一次,就通知其他线程去消费
         * @param o
         */
        public synchronized void put(Object o) {
            while (storage.size() == maxSize) {
                try {
                    System.out.println("仓库满了,开始等待。。。");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            storage.add(o);
            System.out.println("生产了: " + o);
            notify();
        }
    
        /**
         * 取出,为空就进入等待状态,等待别人唤醒后再取
         * 每取出一次,就通知其他线程取生产
         * @return
         */
        public synchronized Object take() {
            while (storage.size() == 0) {
                try {
                    System.out.println("仓库空了,开始等待。。。。");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            Object o = storage.poll();
            System.out.println("消费了:" + o);
            notify();
            return o;
        }
    }
    

    生产者和消费者是两个不同的线程,一个负责生产数据,一个负责消费数据,也就是分别对应仓库的put和take操作

    生产者
    class Producer implements Runnable {
        EventStorage storage;
    
        public Producer(EventStorage storage) {
            this.storage = storage;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++) {
                storage.put(i);
            }
        }
    }
    
    消费者
    
    class Consumer implements Runnable {
        EventStorage storage;
    
        public Consumer(EventStorage storage) {
            this.storage = storage;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++) {
                storage.take();
            }
        }
    }
    
    main方法,测试
     public static void main(String[] args) {
            EventStorage eventStorage = new EventStorage();
            Producer producer = new Producer(eventStorage);
            Consumer consumer = new Consumer(eventStorage);
            Thread t1 = new Thread(producer);
            Thread t2 = new Thread(consumer);
            t1.start();
            t2.start();
    
        }
    
    打印结果

    结果真是太长了,2000多行数据,所以单独放了出来,https://www.jianshu.com/p/ffb8e42fac5f
    打印结果中,大多数都是生产10个,再消费10个,不过也有例外的,比如生产6个,消费6个

    仓库空了,开始等待。。。。
    生产了: 171
    生产了: 172
    生产了: 173
    生产了: 174
    生产了: 175
    生产了: 176
    生产了: 177
    消费了:171
    消费了:172
    消费了:173
    消费了:174
    消费了:175
    消费了:176
    消费了:177
    

    是不是以为它只会把内容全部消费完了才能再生产,不是的,比如这几行打印

    仓库空了,开始等待。。。。
    生产了: 633
    生产了: 634
    生产了: 635
    生产了: 636
    消费了:633
    消费了:634
    消费了:635
    生产了: 637
    生产了: 638
    生产了: 639
    生产了: 640
    生产了: 641
    生产了: 642
    生产了: 643
    生产了: 644
    生产了: 645
    仓库满了,开始等待。。。
    

    这次是先生产4个,再消费3个,再生产9个,生产者进入等待状态(wait)。
    也就是说,每一次执行notify后都有机会让出锁,让另一个线程执行生产或消费的操作,这完全是由jvm控制的。
    待续。。。

    相关文章

      网友评论

          本文标题:生产者消费者模式-wait/notify实现

          本文链接:https://www.haomeiwen.com/subject/wjnmictx.html