share memory 生产者 消费者 生产者消费者动画_System


share memory 生产者 消费者 生产者消费者动画_java_02


share memory 生产者 消费者 生产者消费者动画_System_03

share memory 生产者 消费者 生产者消费者动画_android_04


恭喜辛勤的鱼摊主今日生意火热,瞬间就售空掉捕捞到的鱼。


这里我们把卖鱼当作产出方,顾客当作消费方,其实就是个生产与消费的例子。而生产与消费无处不在,工厂生产玩偶,消费者购买玩偶;餐厅里厨师炒菜,食客吃菜;市场买菜的阿姨卖菜,妈妈们去买菜等等。


假若生产的商品放置于仓库(鱼摊主捕鱼将鱼放置于鱼篓),那么仓库(鱼篓)肯定有个上限,而当仓库无商品(鱼篓无鱼)时候,消费者也无处消费。

我们又如何确保,仓库(鱼篓)满的时候生产者(鱼摊主)停止生产(捕鱼)直到仓库(鱼篓)可以继续存放商品(鱼),仓库(鱼篓)空的时候消费者停止消费直到仓库(鱼篓)又库存(有鱼)?


生产者和消费者是两个独立的并发事件,生产者(鱼摊主他老婆也去捕鱼啦!)生产商品的同时消费者也可能在消费商品。


生产与消费是多线程的经典例子之一,主要涉及到

1.线程等待唤醒

2.同步锁机制


那么我们来看看代码是如何现实的?(注释的地方请注意下)



public static class Producer implements Runnable{
        private List<Object> goods;
        private String name;
        public Producer(List<Object> goods,String name){
            this.name = name;
            this.goods = goods;
        }
        public void product() throws InterruptedException {
            synchronized (goods){//synchronized同步锁goods
                while(goods.size()==10){
                    System.out.println(Thread.currentThread().getName()+" "+name+" "+" goods is full");
                    goods.wait();//线程进入等待状态,并且释放锁goods
                }
                //商品没有满或者处于等待状态的某生产线程唤醒后,执行以下代码
                goods.add(new Object());
                System.out.println(Thread.currentThread().getName()+" "+name+" product,now goods'count is "+goods.size());
                goods.notifyAll();//唤醒在等待的线程
            }
        }
        @Override
        public void run() {
            try {
                product();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static class Consumer implements Runnable{
        private List<Object> goods;
        private String name;
        public Consumer(List<Object> goods,String name){
            this.name = name;
            this.goods = goods;
        }
        public void consume() throws InterruptedException {
            synchronized (goods){//synchronized同步锁goods
                while(goods.size()==0){
                    System.out.println(Thread.currentThread().getName()+" "+name+" "+" goods is empty");
                    goods.wait();//线程进入等待状态,释放锁goods;
                }
                //商品没有空或者处于等待状态的某消费线程唤醒后,执行以下代码
                goods.remove(0);
                System.out.println(Thread.currentThread().getName()+"  "+name+" consume,now goods'count is "+goods.size());
                goods.notifyAll();//唤醒在等待的线程
            }
        }
        @Override
        public void run() {
            try {
                consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出结果(结果顺序不一定相同)

Thread-0 Producer1 product,now goods'count is 1
Thread-1  Consumer1 consume,now goods'count is 0
Thread-2 Consumer2  goods is empty
Thread-3 Consumer3  goods is empty
Thread-4 Producer2 product,now goods'count is 1
Thread-3  Consumer3 consume,now goods'count is 0
Thread-2 Consumer2  goods is empty

本文就只用这个wait/notifyAll来实现生产与消费,但其实还有很多种实现方式,大家可以自己思考下。