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.pswp.cn/web/64100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64100.shtml
英文地址,請注明出處:http://en.pswp.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…