java实现生产者消费者模式

article/2025/9/29 9:17:10

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

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

二: 关系图

在这里插入图片描述

三: 实现方式

  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


http://chatgpt.dhexx.cn/article/IALKWNcX.shtml

相关文章

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

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

生产者/消费者模式

[0]&#xff1a;概述 今天打算来介绍一下“生产者&#xff0f;消费者模式”&#xff0c;这玩意儿在很多开发领域都能派上用场。由于该模式很重要&#xff0c;打算分几个帖子来介绍。今天这个帖子先来扫盲一把。如果你对这个模式已经比较了解&#xff0c;请跳过本扫盲帖&#x…

(四)生产者消费者模式

&#xff08;一)生产者消费者模式原理&#xff1a; 在一个系统中&#xff0c;存在生产者和消费者两种角色&#xff0c;他们通过内存缓冲区进行通信&#xff0c;生产者生产消费者需要的资料&#xff0c;消费者把资料做成产品。生产消费者模式如下图&#xff1a; &#xff08;二…

【C++】【设计模式之】生产者-消费者模型(理论讲解及实现)

一、什么是生产者-消费者模型 1、简单理解生产者-消费者模型 假设有两个进程&#xff08;或线程&#xff09;A、B和一个固定大小的缓冲区&#xff0c;A进程生产数据放入缓冲区&#xff0c;B进程从缓冲区中取出数据进行计算&#xff0c;这就是一个简单的生产者-消费者模型。这里…

设计模式——生产者消费者模式

1 基本概括 2 主要介绍 2.1 概念 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯&#xff0c;而通过阻塞队列来进行通讯&#xff0c;所以生产者生产完数据之后不用等待消费者处理&#xff0c;直接扔给阻塞队列&#xff…

生产者消费者模式三种实现方式

目录 1.什么是生产者消费者模式&#xff1a;2.生产者消费者模型的实现&#xff1a;第一种&#xff1a;使用 synchronized和wait、notify第二种&#xff1a;使用 Lock和await、signal第三种&#xff1a;使用 阻塞队列 BlockingQueue 1.什么是生产者消费者模式&#xff1a; 生产…

t-SNE算法

t-SNE(t-distributed stochastic neighbor embedding)是用于降维的一种机器学习算法&#xff0c;是由 Laurens van der Maaten 和 Geoffrey Hinton在 08 年提出来。t-SNE 是一种非线性降维算法&#xff0c;非常适用于高维数据降维到 2 维或者 3 维&#xff0c;进行可视化。在实…

t-SNE概述

为了循序渐进, 先来学习SNE. SNE 无论是多维数据还是词向量, 都是一个个散落在空间中的点, 点与点之间距离近的, 就可以看作属于同一分类或近义词. 衡量两点距离有很多种手段, 但最常用的还是欧式距离, 所以欧氏距离与相似度的关系可以用某种公式近似表达, 这样就可以把空间信…

机器学习笔记 - 什么是t-SNE?

1、t-SNE概述 t-Distributed Stochastic Neighbor Embedding (t-SNE) 是一种无监督的非线性技术,主要用于数据探索和高维数据的可视化。简单来说,t-SNE 让您对数据在高维空间中的排列方式有一种感觉或直觉。它由 Laurens van der Maatens 和 Geoffrey Hinton 于 2008 年提出。…

可视化降维方法 t-SNE

本篇主要介绍很好的降维方法t-SNE的原理 详细介绍了困惑度perplexity对有效点的影响首先介绍了SNE然后在SNE的基础上进行改进&#xff1a;1.使用对称式。2.低维空间概率计算使用t分布 t-SNE&#xff08;t分布和SNE的组合&#xff09; 以前的方法有个问题&#xff1a;只考虑相…

t-SNE非线性降维

TSNE&#xff08;t-Distributed Stochastic Neighbor Embedding &#xff09;是对SNE的改进&#xff0c;SNE最早出现在2002年&#xff0c;改变了MDN和ISOMAP中基于距离不变的思想&#xff0c;将高维映射到低维的同时&#xff0c;尽量保证相互之间的分布概率不变&#xff0c;SNE…

t-SNE原理及代码

SNE 基本原理 SNE是通过仿射变换将数据点映射到概率分布上&#xff0c;主要包括两个步骤&#xff1a;  &#xff11;) SNE构建一个高维对象之间的概率分布&#xff0c;使得相似的对象有更高的概率被选择&#xff0c;而不相似的对象有较低的概率被选择。   &#xff12;) SN…

t-SNE 原理及Python实例

由于毕业设计有部分工作需要对比两个图像数据集合的差异&#xff0c;为了可视化差异&#xff0c;利用了目前降维首选的t-SNE。我花了点时间看了sklearn里面关于这部分的文档&#xff0c;也查阅了相关博客&#xff0c;最终成功的将两种图片数据集作了一个可视化的对比。我觉得这…

t-SNE算法解析与简单代码实现

t-SNE算法解析与简单代码实现 t-SNESNE基本原理和介绍SNE原理推导t-SNE的引入Symmetric SNE拥挤现象关于 σ \sigma σ的求法 代码解析参数说明 Reference t-SNE t-SNE感觉就是将两个数据点的相似度转换为实际距离的算法 t-SNE(t-distributed stochastic neighbor embedding)是…

t-SNE

t-SNE 文章目录 t-SNE原理SNE(Stochastic Neighbor Embedding)t-SNE对称SNE拥挤问题不匹配的尾部可以补偿不匹配的维度 sklearn.manifold.TSNE参数返回对象的属性Methods 附录Kullback-Leibler divergencest-distributionmanifold learning&#xff08;流形学习&#xff09;Swi…

【33】t-SNE原理介绍与对手写数字MNIST的可视化结果

如有错误&#xff0c;恳请指出。 这篇博客将会介绍一个无监督的降维算法——t-SNE&#xff0c;其是一个常用的降维可视化工具&#xff0c;下面会记录一下李宏毅老师对其的原理介绍&#xff0c;然后我做了一个实验&#xff0c;用其来对手写数字&#xff08;MNIST数据集&#xff…

【论文学习之SNE-RoadSeg】跑通SNE-RoadSeg代码

0 序言 作为一个论文学习的小白&#xff0c;第一次去跑一篇论文代码可谓是下了老大功夫。从一开始的陌生&#xff0c;到现在逐渐熟练&#xff0c;对于如何正确跑通论文代码也有了较为清晰的方法步骤。这段时间跟着学长学习研究论文SNE-RoadSeg&#xff0c;所以接下来我将围绕此…

降维系列之 SNE与t-SNE

t-SNE是一种经典的降维和可视化方法&#xff0c;是基于SNE&#xff08;Stochastic Neighbor Embedding&#xff0c;随机近邻嵌入&#xff09;做的&#xff0c;要了解t-SNE就要先了解SNE。本文同样既是总结&#xff0c;又是读论文笔记。 SNE 随机近邻嵌入 SNE的的第一步是用条…

t-SNE算法详解

前言 此处只作为自己学习理解的笔记之用&#xff0c;转载于https://blog.csdn.net/sinat_20177327/article/details/80298645 t-SNE(t-distributed stochastic neighbor embedding)是用于降维的一种机器学习算法&#xff0c;是由 Laurens van der Maaten 和 Geoffrey Hinton在…

t-SNE数据降维可视化

t-SNE数据降维可视化 – 潘登同学的Machine Learning笔记 文章目录 t-SNE数据降维可视化 -- 潘登同学的Machine Learning笔记 t-SNE的基本思想SNE(Stochastic Neighbor Embedding)SNE的主要缺点距离不对称存在拥挤现象 如何确定 σ \sigma σ总结t-sne代码实现 对比t-sne与UMAP…