• 生产者与消费者问题


    生产者与消费者问题是Java多线程中一道非常经典的问题,问题如下:

      生产者与消费者问题也称缓存问题,生产者与消费者即Java 中的线程,生产者与消费者问题即生产者生产一定数量的线程放入缓存区中,供消费者消费者消费,在消费和生产的过程中,如果生产者生产的产品超过了缓存区的上限则停止生产,等待消费者消费,如果缓存区的产品被消费完,消费者则停止消费,等待生产者生产

       首先,我们来看题目,从题目中我们一个可以抽取出几个实体类呢?答案是4个 Consumer(消费者),Producer(生产者),Product(产品),WareHouse(缓冲区,也叫仓库),于是项目结构如下,main 为测试类

    产品类

    package ProducersAndConsumers;
    
    
    //产品
    public class Product {
    
        //产品需要一个id 来表明产品的唯一性
        private Integer productId;
    
    
        //id直接由构造方法传入
        public Product(Integer productId) {
            this.productId = productId;
        }
    
    
        public Integer getProductId() {
            return productId;
        }
    
    
        @Override
        public String toString() {
            return "Product{" +
                    "productId=" + productId +
                    '}';
        }
    }

    仓库

    package ProducersAndConsumers;
    
    import java.util.LinkedList;
    //仓库类
    public class WareHouse {
    
        //仓库容量,我们设置为10个
        private final int max = 10;
        //仓库基础的数量
        private final int base = 0;
    
    //我们设置一个集合来存放生产的产品,由于我们需要一个可以弹出最后一个产品的方法,所以我们在这里使用LinkedList
        private LinkedList<Product> products = new LinkedList<>();
    
    
        //生产方法
        public synchronized void push(Product product) {
            //判断是否有空间存放产品
            while(max==products.size()){
                try{
                    System.out.println("仓库已满,消费者快来消费"+Thread.currentThread().getName()+"停止生产");
                    //仓库满后停止当前线程
                    this.wait();
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }
            //生产商品
            products.addLast(product);
            System.out.println(Thread.currentThread().getName()+"生产了一个产品:"+product.getProductId()+"号");
            try{
                //等待1秒,方面我们观察
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            notifyAll();
    
        }
    //消费方法
        public synchronized void pop() {
            //判断是否有产品
            while (products.size()==base){
                try{
                    System.out.println("仓库空了,生产者快点生产"+Thread.currentThread().getName()+"停止消费");
                    //仓库空后停止当前线程
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //消费商品
            System.out.println(Thread.currentThread().getName()+"消费了一个产品:"+products.getLast().getProductId()+"号");
            products.removeLast();
            try{
                //等待1秒,方面我们观察
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            notifyAll();
        }
    }

    生产者

    package ProducersAndConsumers;
    //生产者
    public class Producer implements Runnable {
    
        //生产产品的id
        private int count = 0;
    
        //仓库
        private WareHouse wareHouse;
    
        //生产者和消费者都是用同一个仓库,所以我们只要声明一个仓库,在由构造方法传入即可
        public Producer(WareHouse wareHouse) {
            this.wareHouse = wareHouse;
        }
    
        //生产方法
        @Override
        public void run() {
            while (true){
                Product product = new Product(count);
                wareHouse.push(product);
    //            产品id不可重复,所以我们使用自增策略
                count++;
            }
        }
    }

    消费者

    package ProducersAndConsumers;
    
    public class Consumer implements Runnable{
    
        //仓库
        private WareHouse wareHouse;
    
    
        //生产者和消费者都是用同一个仓库,所以我们只要声明一个仓库,在由构造方法传入即可
        public Consumer(WareHouse wareHouse) {
            this.wareHouse = wareHouse;
        }
    
        //消费方法
        @Override
        public void run() {
            while (true){
                wareHouse.pop();
            }
        }
    }

    最后测试类

    package ProducersAndConsumers;
    //测试类
    public class Main {
    
        public static void main(String[] args) {
    
            WareHouse wareHouse = new WareHouse();
    
            Producer producer = new Producer(wareHouse);
            Consumer consumer = new Consumer(wareHouse);
    
            Thread producerT = new Thread(producer,"生产者");
            Thread consumerT = new Thread(consumer,"消费者");
    
            producerT.start();
            consumerT.start();
    
        }
    }
  • 相关阅读:
    Java设计模式之单例模式
    docker常用命令2
    Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate';
    Apache RocketMQ在linux上的常用命令
    RocketMQ的broker启动失败解决
    xshell与xftp使用注意
    Springboot项目打包成jar运行2种方式
    docker常用命令记录
    MySql常用语句总结更新
    springboot启动报错start bean 'eurekaAutoServiceRegistration' NullPointerException
  • 原文地址:https://www.cnblogs.com/liouzeshuen/p/10423142.html
Copyright © 2020-2023  润新知