当前位置: 首页 > article >正文

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.kler.cn/a/455254.html

相关文章:

  • Windows配置cuda,并安装配置Pytorch-GPU版本
  • 探索基金聚合平台的背景与发展:Finanzen.net、Franklin Templeton、Finect
  • 【js】记录预览pdf文件
  • 线性代数行列式
  • fisco-bcos系统架构
  • Redis 应用场景深度探索
  • 深度学习中的并行策略概述:2 Data Parallelism
  • YOLO模型格式转换:pt -> onnx -> rknn
  • 使用Python实现量子电路模拟:走进量子计算的世界
  • 咨询团队如何通过轻量型工具优化项目管理和提高团队协作效率?
  • #渗透测试#漏洞利用#红蓝攻防#信息泄露漏洞#Tomcat信息泄露漏洞的利用
  • 计算机毕设-基于springboot的游戏创意工坊与推广平台的设计与实现(附源码+lw+ppt+开题报告)
  • Jenkins安全部署规范及安全基线
  • 微信小程序UI自动化测试实践 !
  • Browser Use:AI智能体自动化操作浏览器的开源工具
  • 机器学习DAY3续:逻辑回归、极大似然、梯度下降 (逻辑回归完)
  • UE--如何用 Python 调用 C++ 及蓝图函数
  • 达梦数据库-主备集群部署
  • 如何通俗易懂地理解Dockerfile中的NTRYPOINT 和 CMD
  • 消息中间件——rabbitmq,kafka,rocketmq
  • GitHub 上排名前 11 的开源管理后台(Admin Dashboard)项目
  • 宏集eX710物联网工控屏在石油开采机械中的应用与优势
  • 【C++】剖析lower_bound upper_bound
  • Hive on Spark 离线数据仓库中拉链表全流程使用
  • Java设计模式 —— 【结构型模式】外观模式详解
  • 24.try块怎么用 C#例子