转载

漫画:卖鱼与买鱼之生产与消费

漫画:卖鱼与买鱼之生产与消费
漫画:卖鱼与买鱼之生产与消费
漫画:卖鱼与买鱼之生产与消费
漫画:卖鱼与买鱼之生产与消费

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

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

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

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

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

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

1.线程等待唤醒

2.同步锁机制

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

public class ProducerAndConsumer {
    public static void  main(String[] args){
        List<Object> goods = new ArrayList<>();
        Thread p1=new Thread(new Producer(goods,"Producer1"));
        p1.start();
        Thread c1 = new Thread(new Consumer(goods,"Consumer1"));
        c1.start();
        Thread c2 = new Thread(new Consumer(goods,"Consumer2"));
        c2.start();
        Thread c3 = new Thread(new Consumer(goods,"Consumer3"));
        c3.start();
        Thread p2 = new Thread(new Producer(goods,"Producer2"));
        p2.start();
    }
    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来实现生产与消费,但其实还有很多种实现方式,大家可以自己思考下。

从这个多线程经典例子中可以学习到很多有趣的或者你忽略的点。

谢谢大家观阅!

本人公众号程序员七猫,不定期更新!

请多多关注和支持!

(第一时间发布在微信公众号上,所以若是喜欢的朋友可以关注哦)

漫画:卖鱼与买鱼之生产与消费
原文  https://juejin.im/post/5b02e2daf265da0b9265e674
正文到此结束
Loading...