首页 > 编程学习 > 【Java】线程通信:生产者消费者问题

【Java】线程通信:生产者消费者问题

发布时间:2022/11/9 5:20:41

【Java】线程通信:生产者消费者问题

需求

解决生产者消费者的两种方法

  1. 管程法:
  2. 信号灯法

管程法

  1. 利用缓冲区
  2. 步骤
    • 编写产品类Product
    • 编写缓冲区Warehouse
      • 生产者存商品方法
      • 消费者取商品方法
    • 编写生产者类Productor:只负责生产
    • 编写消费者类Cunsomer:只负责消费
    • 编写测试类:启动线程
  3. 代码
    package com.cxl.demo08_communication;
    //管程法:利用缓冲区解决
    //生产者、消费者、产品、缓冲区
    public class Demo08_01_Monitor {
        public static void main(String[] args) {
            Warehouse warehouse = new Warehouse();
            new Productor(warehouse).start();
            new Consumer(warehouse).start();
        }
    }
    class Productor extends Thread{
        Warehouse warehouse;
        public Productor(Warehouse warehouse){
            this.warehouse = warehouse;
        }
        //生产
        @Override
        public void run() {
            for (int i = 1; i <= 100; i++) {
                try {
                    warehouse.push(new Product(i));
                    System.out.println("生产者生产了第"+i+"个产品");
    //                Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }
    class Consumer extends Thread {
        Warehouse warehouse;
        public Consumer (Warehouse warehouse) {
            this.warehouse = warehouse;
        }
        //消费
        @Override
        public void run() {
            for (int i = 1; i <= 100; i++) {
                try {
                    System.out.println("消费者购买了第"+warehouse.pop().id+"个产品");
    //                Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    class Product{
        int id;
    
        public Product(int id) {
            this.id = id;
        }
    }
    class Warehouse{
        Product[] products = new Product[10];   //仓库大小
        int num = 0;
        //生产者存放商品
        public synchronized void push(Product product) throws InterruptedException {
            //判断仓库是否已满
            if (num == products.length) {
                //通知消费者,生产者等待
                this.wait();
            }
    
            products[num] = product;
            num++;
            //通知消费者取出
            this.notifyAll();
        }
        //消费者取出商品
        public synchronized Product pop() throws InterruptedException {
            if (num == 0) {
                //等待消费者生产,消费者等待
                this.wait();
            }
    
            num--;
            Product product = products[num];
            //通知生产者生产
            this.notifyAll();
            return product;
        }
    }
    
    
    

信号灯法

  1. 利用标志位
  2. 步骤
    • 编写产品类Commodity
      • 已有产品,等待消费
        • 通知消费者开始消费
        • 更新产品与信号
      • 无产品,等待生产
        • 通知生产者开始生产
        • 更新信号
    • 编写生产者类Producter:生产产品
    • 编写消费者类Customer:消费产品
    • 编写测试类:启动线程
  3. 代码
    package com.cxl.demo08_communication;
    //信号灯法:利用标志位
    public class Demo08_02_Signal {
        public static void main(String[] args) {
            Commodity commodity = new Commodity();
            new Producter(commodity).start();
            new Customer(commodity).start();
        }
    }
    
    //生产者
    class Producter extends Thread {
        Commodity commodity;
        public Producter(Commodity commodity) {
            this.commodity = commodity;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try{
                    if (i % 3 == 0){
                        this.commodity.production("产品1");
                    }else {
                        this.commodity.production("产品2");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //消费者
    class Customer extends Thread {
        Commodity commodity;
        public Customer(Commodity commodity){
            this.commodity = commodity;
        }
    
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    commodity.custorme();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //产品
    class Commodity{
        String product;
        boolean flag = true;    //启用生产
        //生产者生产,消费者等待
        public synchronized void production(String product) throws InterruptedException {
            if (!flag) {
                this.wait();
            }
            System.out.println("生产者生产了商品:"+product);
            //通知消费者
            this.notifyAll();
            this.product = product;
            this.flag = !this.flag;
        }
        //消费者消费,生产那种等待
        public synchronized void custorme() throws InterruptedException {
            if (flag) {
                this.wait();
            }
            System.out.println("消费者消费了商品:"+product);
            //通知生产者生产
            this.notifyAll();
            this.flag = !this.flag;
        }
    }
    
Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式