GPT带我学-设计模式09-生产者消费者模式

1 什么是生产者消费者模式

生产者消费者模式是一种常见的并发设计模式。在任何系统设计中,如果某处的元素生成和消耗的速度存在差异,都可以使用生产者-消费者模式。

在这种模式中,生产者和消费者是独立且并发执行的线程。它们通过一个共享的、有大小限制的缓冲区(通常是一个队列)进行通信。生产者的任务是生成数据放入缓冲区,消费者的任务是从缓冲区中取出数据。

生产者和消费者的工作速度可能会有所不同,那么:

如果生产者产生数据的速度大于消费者消费的速度,缓冲区会慢慢填满。当缓冲区满时,生产者需要等待消费者消费数据,腾出空间后才能继续生产。
如果消费者消费数据的速度大于生产者产生数据的速度,缓冲区会慢慢被清空。当缓冲区空时,消费者需要等待生产者生产数据,然后才能继续消费。
生产者消费者模式可以帮助我们控制处理流量,平衡生产者和消费者的处理能力,防止资源的过度竞争,提高系统的整体性能。

2 生产者消费者模式有几种类型

生产者消费者模式主要有两种基本形式:

单生产者与单消费者:这是最简单的模型,在这种模型中只有一个生产者生成数据,只有一个消费者来处理数据。

多生产者与多消费者:在这种模型中,存在多个生产者和多个消费者并发工作。例如,一个电商系统中可能有多个线程产生订单(生产者),然后有多个线程处理订单(消费者)。

根据实际需求,还可以存在单生产者多消费者,或者多生产者单消费者的情况。无论哪种形式,核心都是通过一个中间的缓冲区(如队列)进行生产者和消费者的解耦,使得生产者和消费者能够独立且并发地进行工作。

3 请用java写一个单生产者与单消费者的例子帮助我理解

以下是一个使用Java实现的简单的单生产者与单消费者的例子。我们使用一个Java集合类LinkedList作为队列,一个线程作为生产者,一个线程作为消费者。

import java.util.LinkedList;
import java.util.Queue;public class Main {public static void main(String[] args) {Queue<Integer> buffer = new LinkedList<>();int maxSize = 10;Thread producer = new Producer(buffer, maxSize);Thread consumer = new Consumer(buffer);producer.start();consumer.start();}
}class Producer extends Thread {private Queue<Integer> queue;private int maxSize;public Producer(Queue<Integer> queue, int maxSize) {this.queue = queue;this.maxSize = maxSize;}public void run() {for (int i = 0; i < 20; i++) {synchronized (queue) {while (queue.size() == maxSize) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("Producing value : " + i);queue.add(i);queue.notifyAll();}}}
}class Consumer extends Thread {private Queue<Integer> queue;public Consumer(Queue<Integer> queue) {this.queue = queue;}public void run() {while (true) {synchronized (queue) {while (queue.isEmpty()) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("Consuming value : " + queue.remove());queue.notifyAll();}}}
}

在这个例子中,生产者线程会循环20次,每次生成一个数字。当队列大小达到最大大小(maxSize)时,生产者进入等待,等待消费者消费数据。相反,当队列为空时,消费者会等待生产者添加数据到队列。

4 请你再写一个多生产者与多消费者的例子

以下是一个使用Java实现的简单的多生产者与多消费者的例子。我们仍然使用一个Java集合类LinkedList作为队列。

import java.util.LinkedList;
import java.util.Queue;public class Main {public static void main(String[] args) {Queue<Integer> buffer = new LinkedList<>();int maxSize = 10;// 创建两个生产者线程Thread producer1 = new Producer(1, buffer, maxSize);Thread producer2 = new Producer(2, buffer, maxSize);// 创建两个消费者线程Thread consumer1 = new Consumer(1, buffer);Thread consumer2 = new Consumer(2, buffer);producer1.start();producer2.start();consumer1.start();consumer2.start();}
}class Producer extends Thread {private int id;private Queue<Integer> queue;private int maxSize;public Producer(int id, Queue<Integer> queue, int maxSize) {this.id = id;this.queue = queue;this.maxSize = maxSize;}public void run() {for (int i = 0; i < 10; i++) {synchronized (queue) {while (queue.size() == maxSize) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("Producer " + id + " producing value : " + i);queue.add(i);queue.notifyAll();}}}
}class Consumer extends Thread {private int id;private Queue<Integer> queue;public Consumer(int id, Queue<Integer> queue) {this.id = id;this.queue = queue;}public void run() {while (true) {synchronized (queue) {while (queue.isEmpty()) {try {queue.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("Consumer " + id + " consuming value : " + queue.remove());queue.notifyAll();}}}
}

在这个例子中,我们创建了两个生产者线程和两个消费者线程。它们共享同一个队列,并在必要时等待其它线程。运行程序,你将看到生产者和消费者线程交替进行生产和消费操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/110887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【神印王座】伊莱克斯正式登场,皓晨通过永恒试炼,喜提两外挂,采儿丧失四感

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 神印王座动画更新&#xff0c;龙皓晨在雅婷与皓月的帮助下&#xff0c;两次探索悲啸洞穴后成功闯入永恒之塔。在第78集预告中&#xff0c;伊莱克斯闪亮登场&#xff0c;皓晨通过永恒试炼成为新一代死灵圣法师&…

开发小经验积累

今天使用langchain官方文档上的这个包的时候 遇到了这个报错 这个直觉判断肯定是版本问题&#xff0c;我先是去perplexity.ai搜了相关报错 后来没找到什么比较好的回答 这时候想到可以去看当前自己用的版本的langchain的源码&#xff0c;而利用vscode强大的功能&#xff0c;…

Maven Dependency 机制

依赖关系管理是Maven的核心功能。管理单个项目的依赖关系很容易。管理由数百个模块组成的多模块项目和应用程序的依赖关系是可能的。Maven在定义、创建和维护具有良好定义的类路径和库版本的可复制构建方面有很大帮助。 一、传递依赖 Maven通过自动包含可传递的依赖关系&…

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Slider

滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调节、亮度调节等应用场景。该组件从API Version 7开始支持。无子组件 一、接口 Slider(options?: {value?: number, min?: number, max?: number, step?: number, style?: SliderStyle, direction?: Ax…

【Linux】如何判断RS-232串口是否能正常使用

1.RS-232串口短接 使用RS-232协议的串口引脚一般如图下所示 为了让串口能够接收到自己发出的串口数据&#xff0c;需要将输出端和输入端&#xff08;RXD和TXD&#xff09;进行短接操作&#xff1a; 短接完成后&#xff0c;才能实现自发自收的功能&#xff08;走其他协议的串口清…

CUDA编程入门系列(二) GPU硬件架构综述

一、Fermi GPU Fermi GPU如下图所示&#xff0c;由16个SM&#xff08;stream multiprocessor&#xff09;组成&#xff0c;不同的SM之间通过L2 Cache和全局内存进行相连。整个架构大致分为两个层次&#xff0c;①总体架构由多个SM组成 ②每个SM由多个SP core&#xff08;stream…

面试题-消息中间件篇-主流的消息中间件

消息中间件篇 第一章 主流的消息中间件对比 1、主流的消息中间件有 Kafka、RabbitMQ、ActiveMQ 等。 Kafka&#xff1a; Kafka 是一种高吞吐量、分布式、可扩展的发布/订阅消息系统&#xff0c;主要用于大数据处理和分析。Kafka 采用消息日志的方式来存储消息&#xff0c;可以…

springMVC中统一异常处理@ControllerAdvice

1.在DispatcherServlet中初始化HandlerExceptionResolver 2.controller执行完成后执行processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException),有异常则处理异常 3.ExcepitonHandlerExceptionResolver中执行方法doResolveHandlerMethodExceptio…

JavaScript从入门到精通系列第二十一篇:JavaScript中的原型对象详解

文章目录 前言 一&#xff1a;原型对象 1&#xff1a;什么是原型对象 2&#xff1a;原型对象的作用 3&#xff1a;通过原型对象实现工厂方法 二&#xff1a;原型对象咋说 1&#xff1a;in和原型对象 2&#xff1a;hasOwnProperty()函数 3&#xff1a;hasOwnProperty()来…

【计网】计算机网络概述

目录 一、计算机网络的概念 二、计算机网络的组成 1、从组成部分上看 2、从工作方式上看 3、从功能组成上看 三、计算机网络的功能 1、数据通信 2、资源共享 3、分布式处理 4、提高可用性 5、负载均衡 四、计算机网络的分类 1、按分布范围 1.广域网 2.城域网 3.…

竞赛选题 深度学习二维码识别

文章目录 0 前言2 二维码基础概念2.1 二维码介绍2.2 QRCode2.3 QRCode 特点 3 机器视觉二维码识别技术3.1 二维码的识别流程3.2 二维码定位3.3 常用的扫描方法 4 深度学习二维码识别4.1 部分关键代码 5 测试结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天…

【FreeRTOS】【STM32】06 FreeRTOS的使用-动态创建多任务 FreeRTOS 的启动流程

主要流程参照【FreeRTOS】【STM32】06 FreeRTOS的使用-动态创建单任务 1.定义任务句柄 static TaskHandle_t AppTaskCreate_Handle NULL;2.硬件初始化 略 3.创建具体功能任务函数 见定义任务函数 4.使用xTaskCreate创建任务 xReturn xTaskCreate((TaskFunction_t )AppT…

PyTorch 模型性能分析和优化 - 第 6 部分

玩具模型 为了方便我们的讨论&#xff0c;我们使用流行的 timm python 模块&#xff08;版本 0.9.7&#xff09;定义了一个简单的基于 Vision Transformer (ViT) 的分类模型。我们将模型的 patch_drop_rate 标志设置为 0.5&#xff0c;这会导致模型在每个训练步骤中随机丢弃一半…

基于Qt QSpinBox 微调框小案例

修改微调框数值的方式包括: 单击右侧的向上/向下按钮 按键盘的向上/向下键 在微调框获取焦点时,通过鼠标滚轮的上下滚动 当然了,也允许用户手动输入 其中: QSpinBox - 用于整数的显示和输入 QDoubleSpinBox - 用于浮点数的显示和输入 它们都是 QAbstractSpinBox 的子类,具…

线程安全之锁的原理

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1f6f0…

10.7写作练习

慎用定冠词the少用since&#xff0c;多用as&#xff1a;Since there are many TV programs that feature colorful experiences, --> As many TV programs have colourful experiences,动名词作主语&#xff0c;后面加三单注意表意准确无歧义 No, I disagree with the idea …

QCC51XX-QCC30XX系列开发教程(实战篇) 之 12.5-空间音频用开发板调试配置说明

查看全部教程开发请点击:全网最全-QCC51xx-QCC30xx(TWS)系列从入门到精通开发教程汇总(持续更新中) ==================================================================== 版权归作者所有,未经允许,请勿转载。 ==========================================

可观测性-Metrics-WebClient异步Http远程Call

代码示例 1.依赖导入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><ar…

根据ip及子网掩码得出网段

function calculateIPRange(ip, subnetMask) {// 将IP地址和子网掩码转换为二进制形式const ipBinary ip.split(.).map(part > parseInt(part, 10).toString(2).padStart(8, 0)).join();const subnetBinary subnetMask.split(.).map(part > parseInt(part, 10).toStrin…

1019hw

登录窗口头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QToolBar> #include <QMenuBar> #include <QPushButton> #include <QStatusBar> #include <QLabel> #include <QDockWidget>//浮动窗口…