c#多线程之生产者-消费者模型

在 C# 中实现 生产者-消费者模式,通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T> 来作为存储数据的队列,并使用 ThreadMutexMonitor 来确保线程安全。BlockingCollection<T> 是 C# 提供的一个线程安全的集合,可以非常方便地用于实现生产者-消费者模式。

生产者-消费者模式的关键点:

  1. 生产者线程:产生数据并将其放入队列中。
  2. 消费者线程:从队列中取出数据并进行处理。
  3. 线程同步:使用 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();}
}

代码解释:

  1. BlockingCollection<int> queue:一个线程安全的队列,最大容量为 5。BlockingCollection 会在队列满时阻塞生产者线程,在队列为空时阻塞消费者线程。
  2. Producer():模拟生产者线程,每 500 毫秒生成一个数据并放入队列中。如果队列已满,Add 操作会阻塞生产者线程,直到队列有空位。
  3. Consumer():模拟消费者线程,每秒消费一个数据。Take() 会阻塞直到队列中有数据。
  4. 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();}
}

代码解释:

  1. 多个生产者线程:在 Main() 方法中,启动了 2 个生产者线程。每个线程调用 Producer() 方法,生成不同的数据并将其放入共享队列。
  2. 多个消费者线程:启动了 3 个消费者线程,它们从同一个共享队列中取出数据进行处理。

运行结果:

生产者 1 生产数据: 0
生产者 2 生产数据: 0
消费者 1 消费数据: 0
生产者 1 生产数据: 1
消费者 2 消费数据: 1
消费者 3 消费数据: 2
...

总结:

  • BlockingCollection<T> 是 C# 中实现生产者-消费者模式的理想工具。它是线程安全的,支持阻塞操作,且可以容纳多个生产者和消费者。
  • 通过 BlockingCollection<T>AddTake 方法,生产者和消费者可以安全地进行数据交换而无需担心并发问题。
  • 使用多个生产者和消费者线程时,BlockingCollection<T> 会自动处理队列的同步和线程间协调。

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

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

相关文章

选煤厂可视化技术助力智能化运营

通过图扑 HT 可视化搭建智慧选煤厂管理平台&#xff0c;优化了选煤生产流程&#xff0c;提高了资源利用率和安全性&#xff0c;助力企业实现智能化运营和可持续发展目标。

【论文笔记】Visual Alignment Pre-training for Sign Language Translation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Visual Alignment Pre-tra…

深入浅出 MyBatis | CRUD 操作、配置解析

3、CRUD 3.1 namespace namespace 中的包名要和 Dao/Mapper 接口的包名一致&#xff01; 比如将 UserDao 改名为 UserMapper 运行发现抱错&#xff0c;这是因为 UserMapper.xml 中没有同步更改 namespace 成功运行 给出 UserMapper 中的所有接口&#xff0c;接下来一一对…

前端:改变鼠标点击物体的颜色

需求&#xff1a; 需要改变图片中某一物体的颜色&#xff0c;该物体是纯色&#xff1b; 鼠标点击哪个物体&#xff0c;哪个物体的颜色变为指定的颜色&#xff0c;利用canvas实现。 演示案例 代码Demo <!DOCTYPE html> <html lang"en"><head>&l…

递归算法常见问题(Java)

问题&#xff1a;斐波那契数列,第1项和第2项都为1&#xff0c;后面每一项都为相邻的前俩项的和,求第n个数 解法&#xff1a;每一个数都为前俩个数之和&#xff0c;第1项和第2项都为1&#xff0c;所以写 方法f1(n)即为求第n个数&#xff0c;那么f1(n-1)为求第n-1个数&#xff0…

git自动压缩提交的脚本

可以将当前未提交的代码自动执行 git addgit commitgit squash Git 命令安装指南 1. 创建脚本目录 如果目录不存在&#xff0c;创建它&#xff1a; mkdir -p ~/.local/bin2. 创建脚本文件 vim ~/.local/bin/git-squash将完整的脚本代码复制到此文件中。 3. 设置脚本权限…

C项目 天天酷跑(下篇)

上篇再博客里面有&#xff0c;接下来我们实现我们剩下要实现的功能 文章目录 碰撞检测 血条的实现 积分计数器 前言 我们现在要继续优化我们的程序才可以使这个程序更加的全面 碰撞的检测 定义全局变量 实现全局变量 void checkHit() {for (int i 0; i < OBSTACLE_C…

论文解读——掌纹生成网络 RPG-Palm升级版PCE-Palm

该文章是2023年论文RPG-Palm的升级版 论文&#xff1a;PCE-Palm: Palm Crease Energy Based Two-Stage Realistic Pseudo-Palmprint Generation 作者&#xff1a;Jin, Jianlong and Shen, Lei and Zhang, Ruixin and Zhao, Chenglong and Jin, Ge and Zhang, Jingyun and Ding,…

代码随想录算法【Day2】

Day2 1.掌握滑动窗口法 2.模拟题&#xff0c;坚持循环不变量原则 209 长度最小的子数组 暴力法&#xff1a; class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {//暴力法int i, j; //i代表起始点&#xff0c;j代表终止点int sum; //…

android——屏幕适配

一、屏幕适配的重要性 在 Android 开发中&#xff0c;屏幕适配是非常关键的。因为 Android 设备具有各种各样的屏幕尺寸、分辨率和像素密度。如果没有进行良好的屏幕适配&#xff0c;应用可能会出现显示不完整、元素拉伸或压缩变形、字体大小不合适等问题&#xff0c;极大地影响…

oscp学习之路,Kioptix Level2靶场通关教程

oscp学习之路&#xff0c;Kioptix Level2靶场通关教程 靶场下载&#xff1a;Kioptrix Level 2.zip 链接: https://pan.baidu.com/s/1gxVRhrzLW1oI_MhcfWPn0w?pwd1111 提取码: 1111 搭建好靶场之后输入ip a看一下攻击机的IP。 确定好本机IP后&#xff0c;使用nmap扫描网段&…

第二十六周机器学习笔记:PINN求正反解求PDE文献阅读——正问题

第二十六周周报 摘要Abstract文献阅读《Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations》1. 引言2. 问题的设置3.偏微分方程的数据驱动解3.1 连续时间模型3.1.1 …

【安全编码】Web平台如何设计防止重放攻击

我们先来做一道关于防重放的题&#xff0c;答案在文末 防止重放攻击最有效的方法是&#xff08; &#xff09;。 A.对用户密码进行加密存储使用 B.使用一次一密的加密方式 C.强制用户经常修改用户密码 D.强制用户设置复杂度高的密码 如果这道题目自己拿不准&#xff0c;或者…

中关村科金智能客服机器人如何解决客户个性化需求与标准化服务之间的矛盾?

客户服务的个性化和标准化之间的矛盾一直是一个挑战。一方面&#xff0c;企业需要提供标准化的服务以保持运营效率和成本控制&#xff1b;另一方面&#xff0c;为了提升客户满意度和忠诚度&#xff0c;企业又必须满足客户的个性化需求。为此&#xff0c;中关村科金推出了智能客…

OPPO Android面试题及参考答案 (上)

性能优化方面,讲一下图片内存占用计算,以及如何避免持有不必要的引用。 在 Android 中,计算图片内存占用主要与图片的尺寸和像素格式有关。对于一张位图(Bitmap),其内存占用大小可以通过以下方式估算:内存占用 = 图片宽度 图片高度 每个像素占用字节数。例如,常见的 …

Agent 案例分析:金融场景中的智能体-蚂蚁金服案例(10/30)

Agent 案例分析&#xff1a;金融场景中的智能体 —蚂蚁金服案例 一、引言 在当今数字化时代&#xff0c;金融行业正经历着深刻的变革。随着人工智能技术的飞速发展&#xff0c;智能体&#xff08;Agent&#xff09;在金融场景中的应用越来越广泛。蚂蚁金服作为金融科技领域的…

ElasticSearch 的工作原理

理解 ElasticSearch 的工作原理需要从索引、搜索、以及其背后的核心机制几个方面来探讨。 1. ElasticSearch 是什么&#xff1f; ElasticSearch 是一个分布式搜索和分析引擎&#xff0c;适用于各种类型的数据&#xff0c;例如文本、数值、地理位置、结构化或非结构化数据。它基…

STM32F407 | Embedded IDE01 - vscode搭建Embedded IDE开发环境(支持JLINK、STLINK、DAPLINK)

导言 Embedded IDE官网:https://em-ide.com/docs/intro 我猜肯定有部分人使用SI Keil开发STM32项目&#xff0c;也有vscode Keil开发STM32程序。SI或vscode编写代码&#xff0c;然后切换Keil编译、下载、调试程序。有一段时间&#xff0c;我也是这么干的。但是&#xff0c;程…

光谱相机的工作原理

光谱相机的工作原理主要基于不同物质对不同波长光的吸收、反射和透射特性存在差异&#xff0c;以下是其具体工作过程&#xff1a; 一、光的收集 目标物体在光源照射下&#xff0c;其表面会对光产生吸收、反射和透射等相互作用。光谱相机的光学系统&#xff08;如透镜、反射镜…

ThinkPHP接入PayPal支付

ThinkPHP 5接入PayPal 支付&#xff0c;PayPal的流程是服务器请求Paypal的接口下单&#xff08;需要传订单id/支付成功的重定向地址/支付失败的重定向地址&#xff09;&#xff0c;接会返回一个支付地址&#xff0c;项目服务器把地址返给用户&#xff0c;用户打开链接登录Paypa…