c#多线程之生产者-消费者模型
在 C# 中实现 生产者-消费者模式,通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T>
来作为存储数据的队列,并使用 Thread
、Mutex
或 Monitor
来确保线程安全。BlockingCollection<T>
是 C# 提供的一个线程安全的集合,可以非常方便地用于实现生产者-消费者模式。
生产者-消费者模式的关键点:
- 生产者线程:产生数据并将其放入队列中。
- 消费者线程:从队列中取出数据并进行处理。
- 线程同步:使用
BlockingCollection<T>
等线程安全的集合来避免竞争条件,同时确保生产者和消费者之间的协调。
示例:使用 BlockingCollection<T>
C# 提供了 BlockingCollection<T>
类,它可以用来在生产者和消费者线程之间提供同步机制。它是一个线程安全的集合,并支持阻塞操作,因此可以自动协调生产者和消费者的行为。
代码示例:
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;class Program
{// 使用 BlockingCollection 实现线程安全的队列static BlockingCollection<int> queue = new BlockingCollection<int>(5); // 队列最大容量为5// 生产者线程static void Producer(){int item = 0;while (true){Thread.Sleep(500); // 模拟生产延迟// 生产数据并加入队列queue.Add(item);Console.WriteLine("生产者生产数据: " + item);item++;}}// 消费者线程static void Consumer(){while (true){int item = queue.Take(); // 阻塞直到队列中有数据Console.WriteLine("消费者消费数据: " + item);Thread.Sleep(1000); // 模拟消费延迟}}static void Main(){// 启动生产者线程Thread producerThread = new Thread(Producer);producerThread.Start();// 启动消费者线程Thread consumerThread = new Thread(Consumer);consumerThread.Start();// 等待线程结束(实际上,生产者和消费者线程会永远运行下去)producerThread.Join();consumerThread.Join();}
}
代码解释:
BlockingCollection<int> queue
:一个线程安全的队列,最大容量为 5。BlockingCollection
会在队列满时阻塞生产者线程,在队列为空时阻塞消费者线程。Producer()
:模拟生产者线程,每 500 毫秒生成一个数据并放入队列中。如果队列已满,Add
操作会阻塞生产者线程,直到队列有空位。Consumer()
:模拟消费者线程,每秒消费一个数据。Take()
会阻塞直到队列中有数据。Thread.Sleep()
:用来模拟生产和消费的延迟。
BlockingCollection<T>
的关键方法:
Add(T item)
:将项目添加到集合中。如果集合已满,它将阻塞直到有空余空间。Take()
:从集合中移除并返回一个项。如果集合为空,它将阻塞直到有可用项。TryAdd(T item)
:尝试将项目添加到集合中。如果成功则返回true
,否则返回false
,不会阻塞。TryTake(out T item)
:尝试从集合中移除并返回一个项。如果集合为空,返回false
。
扩展:多个生产者和多个消费者
BlockingCollection<T>
支持多个生产者和多个消费者,并且可以通过它来轻松实现复杂的生产者-消费者模型。你只需要启动多个线程来执行生产者和消费者的逻辑即可。
示例:多个生产者和多个消费者
using System;
using System.Collections.Concurrent;
using System.Threading;class Program
{static BlockingCollection<int> queue = new BlockingCollection<int>(5); // 队列最大容量为5// 生产者线程static void Producer(int id){int item = 0;while (true){Thread.Sleep(500); // 模拟生产延迟// 生产数据并加入队列queue.Add(item);Console.WriteLine($"生产者 {id} 生产数据: {item}");item++;}}// 消费者线程static void Consumer(int id){while (true){int item = queue.Take(); // 阻塞直到队列中有数据Console.WriteLine($"消费者 {id} 消费数据: {item}");Thread.Sleep(1000); // 模拟消费延迟}}static void Main(){// 启动多个生产者线程for (int i = 1; i <= 2; i++){int producerId = i;new Thread(() => Producer(producerId)).Start();}// 启动多个消费者线程for (int i = 1; i <= 3; i++){int consumerId = i;new Thread(() => Consumer(consumerId)).Start();}// 主线程等待Console.ReadLine();}
}
代码解释:
- 多个生产者线程:在
Main()
方法中,启动了 2 个生产者线程。每个线程调用Producer()
方法,生成不同的数据并将其放入共享队列。 - 多个消费者线程:启动了 3 个消费者线程,它们从同一个共享队列中取出数据进行处理。
运行结果:
生产者 1 生产数据: 0
生产者 2 生产数据: 0
消费者 1 消费数据: 0
生产者 1 生产数据: 1
消费者 2 消费数据: 1
消费者 3 消费数据: 2
...
总结:
BlockingCollection<T>
是 C# 中实现生产者-消费者模式的理想工具。它是线程安全的,支持阻塞操作,且可以容纳多个生产者和消费者。- 通过
BlockingCollection<T>
的Add
和Take
方法,生产者和消费者可以安全地进行数据交换而无需担心并发问题。 - 使用多个生产者和消费者线程时,
BlockingCollection<T>
会自动处理队列的同步和线程间协调。
相关文章:
c#多线程之生产者-消费者模型
在 C# 中实现 生产者-消费者模式,通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T> 来作为存储数据的队列,并使用 Thread、Mutex 或 Monitor 来确保线程安全。BlockingCollection<T> 是 C# 提供的一个线程安全的集合…...
Spring Boot中幂等性的应用
在 Spring Boot 中,幂等性是实现分布式系统设计和接口调用的一个重要概念,尤其在高并发、分布式环境下,确保接口重复调用不会引发系统数据异常至关重要。 幂等性概念 幂等性(Idempotence)是指一次请求和重复多次请求…...
【机器学习】分类
文章目录 1. 能否用回归解决分类问题2. 生成模型(概率生成)3. 判别模型(逻辑回归)4. 多分类问题 1. 能否用回归解决分类问题 二元分类 数据分布不规律,回归函数会尽量减少误差,导致不合理的偏移离分界较远…...

5.若依的角色权限控制
RBAC 基于角色的访问控制,通过角色来分配和管理用户的菜单权限。 修改课程管理的菜单到主类目下 新建角色并分配菜单 新建用户并分配角色 添加一个根菜单,父级为主类目...

Lumos学习王佩丰Excel第二十三讲:饼图美化与PPT图表
一、双坐标柱形图的补充知识 1、主次坐标设置 2、主次坐标柱形避让(通过增加两个系列,挤压使得两个柱形挨在一起) 增加两个系列 将一个系列设置成主坐标轴,另一个设成次坐标轴 调整系列位置 二、饼图美化 1、饼图美化常见设置 …...

安装winserver2008R2虚拟机步骤
一、服务器系统介绍 1.1什么是服务器? 服务器英文名称为“Server”,指的是网络环境下为客户机(Client)提供某种服务的专用计算机,服务器安装有网络操作系统(如Windows 2000 Server、Linux、Unix等)和各种服务器应用系统软件(如Web服务、电子…...
ACPI PM Timer
ACPI PM Timer 概述: ACPI PM Timer是一个非常简单的计时器,它以 3.579545 MHz 运行,在计数器溢出时生成系统控制中断(SCI)。它精度较低,建议使用其他定时器,如HPET或APIC定时器。 检测ACPI P…...
Linux 和设备树
“开放固件设备树”,简称 Devicetree (DT),是一种用于描述硬件的数据结构和语言。更具体地说,它是操作系统可读取的硬件描述,因此操作系统无需对机器的详细信息进行硬编码。 从结构上看,DT 是一棵树,或具有…...
Qt仿音乐播放器:QFileDialog添加本地文件
一、套路 QFileDialog fileDialog(this);// 创建对话框,并设置父元素;fileDialog.setWindowTitle("添加本地下载的音乐");//设置窗口标题//设置文件对话框的默认打开路径 QString projectPathQDir::currentPath();//获取当前目录 QDir dir(pr…...
Odoo 引用字段 fields.Reference:动态关系的选择器
在 Odoo 模型开发中,关系型字段是构建复杂应用的基础。 然而,传统的 m2o、o2m 和 m2m 字段需要在模型定义时就明确指定关系的目标模型,这在某些场景下会显得不够灵活。 为了解决这个问题,Odoo 提供了 fields.Reference 引用字段&a…...

Android笔试面试题AI答之Android基础(6)
Android入门请看《Android应用开发项目式教程》 文章目录 1.Android Studio版本与Gradle版本有什么关联?**1. Gradle 的作用****2. Android Studio 与 Gradle 的关系****3. 版本对应关系****4. 如何查看和修改版本****查看当前版本****修改版本** **5. 版本不兼容的…...

C# 中的记录类型简介 【代码之美系列】
🎀🎀🎀代码之美系列目录🎀🎀🎀 一、C# 命名规则规范 二、C# 代码约定规范 三、C# 参数类型约束 四、浅析 B/S 应用程序体系结构原则 五、浅析 C# Async 和 Await 六、浅析 ASP.NET Core SignalR 双工通信 …...

利用Java爬虫速卖通按关键字搜索AliExpress商品
在这个信息爆炸的时代,数据的价值日益凸显。对于电商领域的从业者来说,能够快速获取商品信息成为了一项重要的技能。速卖通(AliExpress)作为全球领先的跨境电商平台,拥有海量的商品数据。本文将介绍如何使用Java语言编…...
gitlab runner 实现 微信小程序自动化部署
微信小程序多人开发的情况下,开发人员都只能在本机上发布体验版,且需要到小程序管理后台自行切换到自己发布的版本,会出现体验版本覆盖的问题。给开发测试带来问题。 miniprogram-ci 的发布,使得开发人员可以通过命令行上传小程序…...
Playwright爬虫xpath获取技巧
示例一 <button class"MuiButtonBase-root MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-fullWidth MuiButton-root MuiLoadingButton…...

总结TCP/IP四层模型
总结TCP/IP四层模型 阅读目录(Content) 一、TCP/IP参考模型概述 1.1、TCP/IP参考模型的层次结构二、TCP/IP四层功能概述 2.1、主机到网络层 2.2、网络互连层 2.3、传输层 2.3、应用层 三、TCP/IP报文格式 3.1、IP报文格式3.2、TCP数据段格式3.3、UDP数据段格式3.4、套…...
netcat和nmap的区别
Netcat 和 Nmap 是两种广泛使用的网络工具,但它们的功能和使用场景有所不同。下面是这两种工具的对比: Netcat(nc) 用途和功能: 网络连接: Netcat 是一个功能强大的网络工具,用于创建 TCP 或 UDP 连接。可以用来进行网…...
MinIO服务器文件复制(Windows环境Linux环境)
一、下载 Windows环境:https://dl.min.io/server/minio/release/windows-amd64/minio.exe Linux环境: > curl https://dl.min.io/client/mc/release/linux-amd64/mc \ --create-dirs \ -o $HOME/minio/mc > chmod x $HOME/minio/mc > expo…...

【机器学习】【朴素贝叶斯分类器】从理论到实践:朴素贝叶斯分类器在垃圾短信过滤中的应用
🌟 关于我 🌟 大家好呀!👋 我是一名大三在读学生,目前对人工智能领域充满了浓厚的兴趣,尤其是机器学习、深度学习和自然语言处理这些酷炫的技术!🤖💻 平时我喜欢动手做实…...
无监督学习算法
K-均值聚类(K-means clustering)是一种常用的无监督学习算法,用于将数据集划分成 K 个不同的组或簇。该算法主要通过计算数据点之间的欧几里得距离来确定数据点之间的相似性,并根据相似性将数据点分配到不同的簇中,使得…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...