Java实现简易生产者消费者模型过程解析

一、概述

一共两个线程,一个线程生产产品,一个线程消费产品,使用同步代码块方法,同步两个线程。当产品没有时,通知生产者生产,生产者生产后,通知消费者消费,并等待消费者消费完。

需要注意的是,有可能出现,停止生产产品后,消费者还没未来得及消费生产者生产的最后一个产品,就结束消费,导致最后一个产品没有被消费。

本例使用synchronize以及wait()、notify()实现简易版的线程者消费者模型。

二、测试用例

这里的产品用笔来演示,每只笔都有其编号code

一共有四个类:分别是生产者类,产品类,消费者类,测试类

产品

package test.exception.producer_consumer_model;

/*
假设为产品为笔
 */

public class Production {
  private String type = "";
  private String color = "";
  private long code = 0; // 产品编号
  private boolean isProduced = false; // 是否生产完成 初始状态为未生产状态
  private boolean isContinueProduce = true; // 是否停产该产品

  public void setContinueProduce(boolean continueProduce) {
    isContinueProduce = continueProduce;
  }

  public void setCode(long code) {
    this.code = code;
  }

  public Production(){
  }

  public boolean isContinueProduce() {
    return isContinueProduce;
  }

  public void setType(String type) {
    this.type = type;
  }

  public void setColor(String color) {
    this.color = color;
  }

  public void setProduced(boolean produced) {
    isProduced = produced;
  }

  public boolean isProduced() {
    return isProduced;
  }

  @Override
  public String toString() {
    return color + type + "-" + code;
  }
}

生产者

package test.exception.producer_consumer_model;

public class Producer implements Runnable {
  private final Production pen; // 产品

  public Producer(Production pen) {
    this.pen = pen;
  }

  // 生产
  public void produce() {
    long code = 0;
    while (this.pen.isContinueProduce()) {
      synchronized (this.pen) {
        if (this.pen.isProduced()) {
          try {
            this.pen.wait(); // 等待消费者消费
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        // 开始生产
        this.pen.setType("铅笔");
        this.pen.setColor("蓝色");
        this.pen.setCode(code++);
        this.pen.setProduced(true);
        System.out.println(this.pen + " is produced");
        this.pen.notify();
      }
    }
    System.out.println("finish producing");
  }
  @Override
  public void run() {
    produce();
  }
}

消费者

package test.exception.producer_consumer_model;

public class Consumer implements Runnable {
  private final Production pen;

  public Consumer(Production pen) {
    this.pen = pen;
  }

  // 持续消费
  public void consumer() {
    while (this.pen.isContinueProduce()) {
      synchronized (this.pen) {
        if (!this.pen.isProduced()) {
          try {
            this.pen.wait(); // 等待生产者生产
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

        System.out.println(this.pen + " is consumed"); // 使用
        this.pen.setProduced(false); // 使用完后更新状态
        this.pen.notify();
      }
    }
    // 确保停止生产后,能够使用最后生产的一支笔
    if (this.pen.isProduced()) {
      System.out.println(this.pen + " is consumed");
    }

    System.out.println("finish using");
  }

  @Override
  public void run() {
    consumer();
  }
}

主线程测试

package test.exception.producer_consumer_model;

public class Demo {
  public static void main(String[] args) throws InterruptedException {
    Production pen = new Production();
    Consumer consumer = new Consumer(pen);
    Producer producer = new Producer(pen);
    new Thread(producer).start(); // 开启生产者线程
    new Thread(consumer).start(); // 开启消费者线程

    Thread.sleep(10000);
    pen.setContinueProduce(false); // 10s后停止生产该类型的笔
  }
}

运行结果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相同的,这体现的是一种线程间通信方式. 本文将先说明单生产者单消费者的情况,之后再说明多生产者多消费者模式的情况.还会分别使用wait()/nofity()/nofityAll()机制.lock()/unlock()机制实现这两种模式. 在开始介绍模式之前,先解释下wait().notify()和no

  • Java中生产者消费者问题总结

    生产者-消费者算是并发编程中常见的问题.依靠缓冲区我们可以实现生产者与消费者之间的解耦.生产者只管往缓冲区里面放东西,消费者只管往缓冲区里面拿东西.这样我们避免生产者想要交付数据给消费者,但消费者此时还无法接受数据这样的情况发生. wait notify 这个问题其实就是线程间的通讯,所以要注意的是不能同时读写.生产者在缓冲区满的时候不生产,等待:消费者在缓冲区为空的时候不消费,等待.比较经典的做法是wait和notify. 生产者线程执行15次set操作 public class Produc

  • 浅谈Java中生产者与消费者问题的演变

    想要了解更多关于Java生产者消费者问题的演变吗?那就看看这篇文章吧,我们分别用旧方法和新方法来处理这个问题. 生产者消费者问题是一个典型的多进程同步问题. 对于大多数人来说,这个问题可能是我们在学校,执行第一次并行算法所遇到的第一个同步问题. 虽然它很简单,但一直是并行计算中的最大挑战 - 多个进程共享一个资源. 问题陈述 生产者和消费者两个程序,共享一个大小有限的公共缓冲区. 假设一个生产者"生产"一份数据并将其存储在缓冲区中,而一个消费者"消费"这份数据,并将

  • Java多线程 生产者消费者模型实例详解

    生产者消费者模型 生产者:生产任务的个体: 消费者:消费任务的个体: 缓冲区:是生产者和消费者之间的媒介,对生产者和消费者解耦. 当 缓冲区元素为满,生产者无法生产,消费者继续消费: 缓冲区元素为空,消费者无法消费,生产者继续生产: wait()/notify()生产者消费者模型 制作一个简单的缓冲区ValueObject,value为空表示缓冲区为空,value不为空表示缓冲区满 public class ValueObject { public static String value = "

  • Java多种方式实现生产者消费者模式

    实现需求:两个线程交替打印1,0,打印10轮 java多线程口诀: 高内聚,低耦合 线程操作资源类 判断干活通知 防止虚假唤醒 方式一:使用synchronized和Object的wait和notifyAll方法 wait:使当前线程阻塞 notify,notifyAll唤醒当前线程 /** * 两个线程交替打印1,0 打印10轮 * * @author Administrator * @version 1.0 2020年7月12日 * @see ProdConsumerDemo1 * @sin

  • Java多线程生产者消费者模式实现过程解析

    单生产者与单消费者 示例: public class ProduceConsume { public static void main(String[] args) { String lock = new String(""); Produce produce = new Produce(lock); Consume consume = new Consume(lock); new Thread(() -> { while (true) { produce.setValue();

  • Java生产者消费者模式实例分析

    本文实例讲述了Java生产者消费者模式.分享给大家供大家参考,具体如下: java的生产者消费者模式,有三个部分组成,一个是生产者,一个是消费者,一个是缓存. 这么做有什么好处呢? 1.解耦(去依赖),如果是消费者直接调用生产者,那如果生产者的代码变动了,消费者的代码也需要随之变动 2.高效,如果消费者直接掉生产者,执行时间较长的话,会阻塞,影响其他业务的进行 3.负载均衡,如果消费者直接调生产者,那生产者和消费者就得在一起了,日后业务量非常大的话,要想减轻服务器的压力,想拆分生产和消费,就很困

  • Java多线程并发生产者消费者设计模式实例解析

    一.两个线程一个生产者一个消费者 需求情景 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个. 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法是采用标记或加锁机制. wait() / nofity() 方法是基类Object的两个方法,也就意味着所有Java类都会拥有这两个方法,这样,我们就可以为任何对象实现同步机制. wait()方法:当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行. not

  • Java实现Kafka生产者消费者代码实例

    Kafka的结构与RabbitMQ类似,消息生产者向Kafka服务器发送消息,Kafka接收消息后,再投递给消费者. 生产者的消费会被发送到Topic中,Topic中保存着各类数据,每一条数据都使用键.值进行保存. 每一个Topic中都包含一个或多个物理分区(Partition),分区维护着消息的内容和索引,它们有可能被保存在不同服务器. 新建一个Maven项目,pom.xml 加入依赖: <dependency> <groupId>org.apache.kafka</gro

  • Java多线程 BlockingQueue实现生产者消费者模型详解

    BlockingQueue BlockingQueue.解决了多线程中,如何高效安全"传输"数据的问题.程序员无需关心什么时候阻塞线程,什么时候唤醒线程,该唤醒哪个线程. 方法介绍 BlockingQueue是Queue的子类 void put(E e) 插入指定元素,当BlockingQueue为满,则线程阻塞,进入Waiting状态,直到BlockingQueue有空闲空间再继续. 这里以ArrayBlockingQueue为例进行分析 void take() 队首出队,当Bloc

随机推荐