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


    【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
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87

    信号灯法

    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;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
  • 相关阅读:
    freemarker 生成word,支持循环导出图片 WPS版本
    FFmpeg源码剖析-通用:ffmpeg_parse_options()
    5个 Istio 访问外部服务流量控制最常用的例子,你知道几个?
    LiveCharts WPF 实时数据慢。提高 LiveCharts 实时绘图性能
    windows安装配置JDK和Tomcat
    【华为机试真题 JAVA】组成最大数-100
    14. Longest Common Prefix
    递归、搜索与回溯算法——穷举vs暴搜vs深搜
    SSM_整合篇
    2023 年高教社杯全国大学生数学建模竞赛题目 B 题 多波束测线问题
  • 原文地址:https://blog.csdn.net/weixin_57807561/article/details/127758308