zoukankan      html  css  js  c++  java
  • 手写一个生产者消费者模式

    主要是如何使用wait notify/notifyAll

    先定义生产和消费的方法(同步问题)

    public class Storage {
    
        /**
         * 仓库最大容量
         */
        private static int MAX_VALUE = 100;
    
        /**
         * 储存产品
         */
        private List<Object> list = new ArrayList<>();
    
        /**
         * 生产num个产品
         * @param num
         */
        public void produce(int num) {
            synchronized (list) {
                //一定是while,因为wait被唤醒后需要判断是不是满足生产条件;仓库剩余的容量不足以存放即将要生产的数量,暂停生产;要注意,notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。所以在进行条件判断时候,可以先把 wait 语句忽略不计来进行考虑,显然,要确保程序一定要执行,并且要保证程序直到满足一定的条件再执行,要使用while来执行,以确保条件满足和一定执行
                while (list.size() + num > MAX_VALUE) {
                    System.out.println("暂时不能执行生产任务");
    
                    try {
                        //条件不满足,生产阻塞,会释放当前的锁,然后让出CPU,进入等待状态
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
                //满足条件后开始生产
                for (int i = 0; i < num; i++) {
                    list.add(new Object());
                }
                System.out.println("已生产产品数"+num+" 仓库容量"+list.size());
                //只有当 notify/notifyAll() 被执行时候,才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。
                list.notifyAll();
            }
        }
    
        /**
         * 消费num个产品
         * @param num
         */
        public void consume(int num) {
            synchronized (list) {
                while (list.size() < num) {
                    System.out.println("暂时不能执行消费任务");
    
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
                //满足条件后开始消费
                for (int i = 0; i < num; i++) {
                    list.remove(0);
                }
                System.out.println("已消费产品数"+num+" 仓库容量" + list.size());
    
                list.notifyAll();
            }
        }
    }

    定义生产者线程

    public class Producer extends Thread {
    
        /**
         * 生产产品个数
         */
        private int num;
    
        private Storage storage;
    
        public Producer(Storage storage) {
            this.storage = storage;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public void run() {
            storage.produce(getNum());
        }
    }

    定义消费者线程

    public class Customer extends Thread {
    
        /**
         * 消费产品个数
         */
        private int num;
    
        private Storage storage;
    
        public Customer(Storage storage) {
            this.storage = storage;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public void run() {
            storage.consume(getNum());
        }
    }

    最后写一个测试类,用来开启多个生产者,消费者线程执行操作

    public class Test {
    
        public static void main(String[] args) {
            Storage storage = new Storage();
    
            Producer p1 = new Producer(storage);
            Producer p2 = new Producer(storage);
            Producer p3 = new Producer(storage);
            Producer p4 = new Producer(storage);
    
            Customer c1 = new Customer(storage);
            Customer c2 = new Customer(storage);
            Customer c3 = new Customer(storage);
    
            p1.setNum(10);
            p2.setNum(20);
            p3.setNum(10);
            p4.setNum(80);
    
            c1.setNum(50);
            c2.setNum(20);
            c3.setNum(20);
    
            c1.start();
            c2.start();
            c3.start();
    
            p1.start();
            p2.start();
            p3.start();
            p4.start();
    
        }
    }

    运行得到的结果为:

    暂时不能执行消费任务
    暂时不能执行消费任务
    暂时不能执行消费任务
    已生产产品数10 仓库容量10
    暂时不能执行消费任务
    暂时不能执行消费任务
    已生产产品数20 仓库容量30
    已生产产品数10 仓库容量40
    暂时不能执行生产任务
    暂时不能执行消费任务
    已消费产品数20 仓库容量20
    已消费产品数20 仓库容量0
    暂时不能执行消费任务
    已生产产品数80 仓库容量80
    已消费产品数50 仓库容量30

    核心的就是每个线程拿到锁之后检测是不是满足条件,不满足则wait释放锁及CPU资源,等待被唤醒之后判断条件满足的话执行生产/消费操作,然后唤醒别的等待的线程,此线程结束

  • 相关阅读:
    Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    用户画像——“打标签”
    python replace函数替换无效问题
    python向mysql插入数据一直报TypeError: must be real number,not str
    《亿级用户下的新浪微博平台架构》读后感
    【2-10】标准 2 维表问题
    【2-8】集合划分问题(给定要分成几个集合)
    【2-7】集合划分问题
    【2-6】排列的字典序问题
    【2-5】有重复元素的排列问题
  • 原文地址:https://www.cnblogs.com/liuqing576598117/p/11233250.html
Copyright © 2011-2022 走看看