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资源,等待被唤醒之后判断条件满足的话执行生产/消费操作,然后唤醒别的等待的线程,此线程结束

  • 相关阅读:
    如何在Google Map中处理大量标记(ASP.NET)(转)
    MapXtreme在asp.net中的使用之加载地图(转)
    Oracle数据类型与.NET中的对应关系(转)
    GIS-开发例程、源代码、MapXtreme、Map (转)
    Win7 64位系统上配置使用32位的Eclipse(转)
    视频会议十大开源项目排行(转)
    RTMP流媒体播放过程(转)
    python中如何将生成等差数列和等比数列
    python中type dtype astype 的用法
    python类库numpy中常见函数的用法
  • 原文地址:https://www.cnblogs.com/liuqing576598117/p/11233250.html
Copyright © 2011-2022 走看看