zoukankan      html  css  js  c++  java
  • Java多线程10-生产者消费者问题

    1、生产/消费者模型

    生产/消费者模型是一个典型的多线程问题,涉及到的对象包括“生产者”、“消费者”、“仓库”和“产品”。它们之间的关系如下;
    (01)生产者仅仅在仓库未满的时候生产,仓库满了则停止生产

    (02)消费者仅仅在仓库有产品的时候才能消费,仓库空则等待

    (03)当消费者发现仓库没有产品的时候会通知生产者生产

    (04)生产者在生产出可消费的产品时,应该通知等待的消费者去消费

    2、实现

    class Depot
    {
        private int capacity; //仓库容量
        private int size; //仓库的实际数量
    
        public Depot(int capacity)
        {
            this.capacity = capacity;
            this.size = 0;
        }
    
        public synchronized void produce(int val)
        {
            try
            {
                int left = val; //表示想要生产的数量
                while(left > 0)
                {
                    while(size >= capacity) //仓库满了,等待消费者
                        wait();
    
                    //计算实际增量
                    //如果库存+想要生产的数量 > 容量,则“实际增量” = “容量” - “当前容量”(这样会填满仓库)
                    //否则,增量 = 想要生产的数量
                    int increment = (size+left) > capacity ? (capacity-size) : left;
                    size = size + increment;
                    left = left - increment;
                    System.out.printf("%S produce(%d) --> left = %d,inc = %d, size = %d
    ",
                            Thread.currentThread().getName(),val,left,increment,size);
    
                    notifyAll();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    
        public synchronized void consume(int val)
        {
            try
            {
                int left = val;
                while(left > 0)
                {
                    while(size <= 0)
                        wait();
    
                    int decrement = size < left ? size : left;
                    size = size - decrement;
                    left = left - decrement;
                    System.out.printf("%s consume(%d) <-- left = %d, dec = %d, size = %d
    ",
                            Thread.currentThread().getName(),val,left,decrement,size);
                    notifyAll();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    
        public String toString()
        {
            return "capacity:"+capacity+", actual size:"+size;
        }
    }
    class Customer
    {
        private Depot depot;
    
        public Customer(Depot depot)
        {
            this.depot = depot;
        }
    
        public void consume(final int val)
        {
            new Thread()
            {
                public void run()
                {
                    depot.consume(val);
                }
            }.start();
        }
    }
    
    class Producer
    {
        private Depot depot;
    
        public Producer(Depot depot)
        {
            this.depot = depot;
        }
    
        public void produce(final int val)
        {
            new Thread()
            {
                public void run()
                {
                    depot.produce(val);
                }
            }.start();
        }
    }
    
    public class Demo
    {
        public static void main(String[] args)
        {
            Depot mDepot = new Depot(100);
            Producer mPro = new Producer(mDepot);
            Customer mCus = new Customer(mDepot);
    
            mPro.produce(60);;
            mPro.produce(120);
            mCus.consume(90);
            mCus.consume(150);
            mPro.produce(110);
        }
    }

    运行结果:

    THREAD-0 produce(60) --> left = 0,inc = 60, size = 60
    THREAD-4 produce(110) --> left = 70,inc = 40, size = 100
    Thread-3 consume(150) <-- left = 50, dec = 100, size = 0
    THREAD-1 produce(120) --> left = 20,inc = 100, size = 100
    Thread-2 consume(90) <-- left = 0, dec = 90, size = 10
    Thread-3 consume(150) <-- left = 40, dec = 10, size = 0
    THREAD-4 produce(110) --> left = 0,inc = 70, size = 70
    Thread-3 consume(150) <-- left = 0, dec = 40, size = 30
    THREAD-1 produce(120) --> left = 0,inc = 20, size = 50

    五个线程都把自己想生产或者想消费的执行完毕

  • 相关阅读:
    嵌入式工程师C语言面试常见的0x10个问题
    C语言初学者网站推荐
    strlen和sizeof
    基于Docker搭建GitLab和Maven私服
    linux暴露端口可以被外部访问
    MySQL新增用户及赋予权限
    Docker添加域名解析
    Netstat 网络命令详解
    Mysql索引太长导致同步数据结构失败解决方法
    完美解决Cannot download "https://github.com/sass/node-sass/releases/download/binding.nod的问题
  • 原文地址:https://www.cnblogs.com/qumasha/p/12824943.html
Copyright © 2011-2022 走看看