一: 什么是生产者消费者模型

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
简单来说:
       生产者消费者模型就是指,在一个系统中,存在两种角色,一个为生产者,一个为消费者,通过一个缓冲区(仓库)进行通信,生产者将生产的产品放入仓库,消费者从仓库中取产品。当仓库满时,生产者阻塞,当仓库空时,消费者阻塞。

二: 关系图

三: 实现方式

  1. 采用 wait—notify 的方式
  2. 采用 阻塞队列 方式

3.1 wait—notify 方式

3.1.1 举例1

生产者类

/*** 生产者类* 实现runnable接口* @author DH**/
public class Producer implements Runnable{private BufferArea ba;//通过传入参数的方式是使得对象相同,具有互斥锁的效果。public Producer(BufferArea ba){this.ba = ba;}@Overridepublic void run() {while(true){setIntervalTime();ba.set();//生产产品}}//设置时间间隔public void setIntervalTime(){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}

消费者类

/*** 消费者类* 实现runnable接口* @author DH**/
public class Consumer implements Runnable{private BufferArea ba;public Consumer(BufferArea ba){this.ba = ba;}@Overridepublic void run() {while(true){setIntervalTime();ba.get();//消费产品}}//设置时间间隔public void setIntervalTime(){try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}
}

仓库 

/*** 仓库* 缓冲区* wait()/notify()* @author DH**/
public class BufferArea {private int currNum = 0;//当前仓库的产品数量private int maxNum = 10;//仓库最大产品容量public synchronized void set(){if(currNum<maxNum){currNum++;System.out.println(Thread.currentThread().getName()+" 生产了一件产品!当前产品数为:"+currNum);notifyAll();}else{//当前产品数大于仓库的最大容量try {System.out.println(Thread.currentThread().getName()+" 开始等待!当前仓库已满,产品数为:"+currNum);wait();} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void get(){if(currNum>0){//仓库中有产品currNum--;System.out.println(Thread.currentThread().getName()+" 获得了一件产品!当前产品数为:"+currNum);notifyAll();}else{try {System.out.println(Thread.currentThread().getName()+" 开始等待!当前仓库为空,产品数为:"+currNum);wait();} catch (InterruptedException e) {e.printStackTrace();}}}
}

测试类

/*** 测试类* @author DH**/
public class MainCode {public static void main(String[] args) {//同一个仓库BufferArea ba = new BufferArea();//三个生产者Producer p1 = new Producer(ba);Producer p2 = new Producer(ba);Producer p3 = new Producer(ba);//三个消费者Consumer c1 = new Consumer(ba);Consumer c2 = new Consumer(ba);Consumer c3 = new Consumer(ba);//创建线程,并给线程命名Thread t1 = new Thread(p1,"生产者1");Thread t2 = new Thread(p2,"生产者2");Thread t3 = new Thread(p3,"生产者3");Thread t4 = new Thread(c1,"消费者1");Thread t5 = new Thread(c2,"消费者2");Thread t6 = new Thread(c3,"消费者3");//使线程进入就绪状态t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();}
}

通过设置生产者消费者的时间间隔,可以测试仓库满和空时的情况,当生产者时间间隔小,表示生产的快,会出现仓库满了的情况。测试结果如下。

生产者2 生产了一件产品!当前产品数为:1
生产者1 生产了一件产品!当前产品数为:2
生产者3 生产了一件产品!当前产品数为:3
生产者3 生产了一件产品!当前产品数为:4
生产者1 生产了一件产品!当前产品数为:5
生产者2 生产了一件产品!当前产品数为:6
生产者1 生产了一件产品!当前产品数为:7
生产者3 生产了一件产品!当前产品数为:8
生产者2 生产了一件产品!当前产品数为:9
生产者3 生产了一件产品!当前产品数为:10
生产者2 开始等待!当前仓库已满,产品数为:10
生产者1 开始等待!当前仓库已满,产品数为:10
消费者1 获得了一件产品!当前产品数为:9
消费者2 获得了一件产品!当前产品数为:8

当消费者时间间隔小,表示消费的快,会出现仓库为空的情况。测试结果如下。

消费者2 开始等待!当前仓库为空,产品数为:0
生产者3 生产了一件产品!当前产品数为:1
生产者2 生产了一件产品!当前产品数为:2
生产者1 生产了一件产品!当前产品数为:3
消费者2 获得了一件产品!当前产品数为:2
消费者1 获得了一件产品!当前产品数为:1
消费者3 获得了一件产品!当前产品数为:0
消费者3 开始等待!当前仓库为空,产品数为:0

3.1.2 举例2

产品类(仓库)

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;}@Overridepublic 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");}@Overridepublic 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");}@Overridepublic 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后停止生产该类型的笔}
}

运行结果 

3.2 阻塞队列方式

这里因为篇幅原因, 详细的实现方式可以看我的这篇博客; https://blog.csdn.net/m0_50370837/article/details/124339524

参考文章: Java的生产者消费者模型_Hi--Man的博客-CSDN博客

https://www.jb51.net/article/187908.htm

java实现生产者消费者模式相关推荐

  1. 【JAVA】生产者消费者模式

    首先要思考一个问题:为什么要使用这种模式进行生产代码. 优点: 极大的解决了代码之间的耦合程度 解释: 之前我们写的代码可能是这样的,有A和B 两个功能代码处理数据,B代码的执行必须要依赖于A代码才能 ...

  2. 【Java】生产者消费者模式的三种实现

    原文地址:https://blog.csdn.net/u010983881/article/details/78554671 前言 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内 ...

  3. 【Java】生产者消费者模式的实现

    前言 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力.这个 ...

  4. java 实现生产者-消费者模式

    生产和消费者模式有很多种,现在介绍几种常见的方式 wait/notify实现生产和消费者模式 1.使用wait/notify实现生产和消费者模式: public class Depot {// 实际容 ...

  5. java多线程-生产者消费者模式

    进程定义: 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位 线程定义: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能 ...

  6. 生产者消费者模式-java原生、Disruptor实现方案

    生产者消费者模式介绍 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻 ...

  7. java lock condition_Java 通过 Lock 和 竞争条件 Condition 实现生产者消费者模式

    更多 Java 并发编程方面的文章,请参见文集<Java 并发编程> 竞争条件 多个线程共享对某些变量的访问,其最后结果取决于哪个线程偶然在竞争中获胜. condition.await() ...

  8. java消费者模式_基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  9. Java并发编程实战~生产者-消费者模式

    前面我们在<Worker Thread 模式>中讲到,Worker Thread 模式类比的是工厂里车间工人的工作模式.但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域,就 ...

最新文章

  1. Mysql使用存储过程快速添加百万数据
  2. Redmine+Apache+SVN+Postfix完整配置指南
  3. 国外程序员收集整理的PHP资源大全
  4. 在Java EE 7和WildFly中使用Bean验证来验证JAX-RS资源数据
  5. 转:ORA-01126: 数据库必须已装载到此实例并且不在任何实例中打开
  6. Java基础05 break和continue比较区别
  7. 配置nginx+wordpress的https
  8. 虚拟机中qemu模拟开发板启动过程,使用nfs挂载根文件系统
  9. 数据交互之封装request请求(微信小程序篇)
  10. .net实现调用本地exe等应用程序的办法总结
  11. 2021-07-01样式和图片标签
  12. 【零基础】speech driven animation中文安装使用指南
  13. HIP HOP 街舞文化
  14. JSPServlet(5)——实现简单的留言簿功能
  15. C语言——相关学习资源网站及工具
  16. 转载分享一批老外的超牛25行代码参赛作品的Flash源文件
  17. 文本分类半监督学习--UDA
  18. Django计算机毕业设计爱宝贝影楼管理系统(程序+LW)Python
  19. R语言之非线性回归xt9.5
  20. NHibernate学习

热门文章

  1. 如何在eclipse中安装Jess
  2. 人生感悟人生是一场修行
  3. 基于JAVA干洗店订单管理系统设计与实现计算机毕业设计源码+数据库+lw文档+系统+部署
  4. 《 Android物联网开发从入门到实战》
  5. D35 876. Middle of the Linked List
  6. 写给所有程序员的心声~千里马常有,但伯乐不常有
  7. java gravity_Android属性gravity与layout_gravity的区别
  8. 谷歌protobuf(Protocol buffers)的使用
  9. mysql 百亿数据_从SQL Server到MySQL,近百亿数据量迁移实战
  10. 生物电镜常见问题及解答