C#队列Queue详解

一问题

假设:

你在做上位机。

有两个线程:


线程1(PLC采集线程)

不停读取PLC:

复制代码
每10ms读取一次数据

线程2(数据库线程)

负责保存数据:

复制代码
保存一次需要100ms

问题来了

PLC数据来的速度:

复制代码
远远快于数据库保存速度

怎么办?

二解决办法:队列缓冲

先存起来,搞一个队列出来,PLC线程只负责采集数据,然后放入队列,数据库线程,慢慢从队列中取数据,保存到数据库

这就是生产者消费者模型

三普通队列Queue

3.1.场景

平常存数据用,集合,数组,数据库都是随便查,随便删,随机访问。

而队列不支持随机访问,只能先进先出

场景1:消息排队

  • 聊天消息接收
  • 订单处理
  • 日志写入
  • 后台任务排队
  • 游戏技能释放队列

场景 2:广度优先搜索 BFS(算法)

比如迷宫寻路、层级遍历,必须用队列。

场景 3:异步任务排队

比如:

  • 上传文件队列
  • 打印队列
  • 接口请求限流队列

这些都是必须排队的业务。

3.2特点

  • 只能从尾部加数据
  • 只能从头部取数据
  • 不能随机访问(不能取第 3 个、第 5 个)
  • 按顺序处理
  • 内部自动扩容
  • 配合 BFS(广度优先)必用

3.3核心方法

方法 作用
Enqueue(item) 把数据加到队尾
Dequeue() 取出并删除队首数据
Peek() 查看队首,但不删除
Clear() 清空队列
Contains(item) 判断是否包含某个数据

额外常用:

  • Count:队列里有多少个数据

3.4实例

cs 复制代码
// 1. 创建队列
Queue<string> queue = new Queue<string>();

// 2. 入队(加到尾部)
queue.Enqueue("第1个人");
queue.Enqueue("第2个人");
queue.Enqueue("第3个人");

// 现在队列:第1 → 第2 → 第3


// 3. 查看队首(不删除)
string first = queue.Peek(); 
Console.WriteLine(first); // 输出:第1个人


// 4. 出队(取出并删除队首)
string a = queue.Dequeue(); // 取出:第1个人
string b = queue.Dequeue(); // 取出:第2个人

// 现在队列只剩:第3个人


// 5. 遍历队列(不会删除数据)
foreach(var item in queue)
{
    Console.WriteLine(item);
}

四多线程安全队列ConcurrentQuenue

4.1用途

ConcurrentQueue = 线程安全的队列 专门给多线程、并发场景用的。

如果:

  • 线程 A:往队列加数据
  • 线程 B:从队列取数据

普通 Queue 会直接崩溃、数据丢失、卡死

ConcurrentQueue 就是为了解决这个问题诞生的!

4.2特点

  1. 线程安全
  2. 先进先出
  3. 无锁/轻量级锁
  4. 不能修改中间元素
  5. 不能随机访问
  6. 配合多线程BFS也能用

4.3核心方法

方法 作用
Enqueue(item) 加到队尾(和普通 Queue 一样)
TryDequeue(out item) 尝试取出队首,并删除(安全取出)
TryPeek(out item) 尝试查看队首,不删除
IsEmpty 判断队列是否为空
Count 元素数量(不推荐频繁用)

**为什么带 Try?**多线程时,可能刚好被别的线程取走了,所以要 "尝试取"。

4.4实例

cs 复制代码
// 1. 创建并发队列
ConcurrentQueue<int> queue = new ConcurrentQueue<int>();

// 2. 入队(和普通一样)
queue.Enqueue(10);
queue.Enqueue(20);
queue.Enqueue(30);

// 3.  Try 取出队首(安全!)
if (queue.TryDequeue(out int result))
{
    Console.WriteLine("取出:" + result); // 10
}

// 4. Try 查看队首(不删除)
if (queue.TryPeek(out int first))
{
    Console.WriteLine("队首是:" + first); // 20
}

// 5. 判断空
bool empty = queue.IsEmpty;

4.5场景实例

cs 复制代码
// 并发队列
ConcurrentQueue<string> taskQueue = new ConcurrentQueue<string>();

// 生产者线程:往队列加任务
Task.Run(() =>
{
    for (int i = 1; i <= 5; i++)
    {
        taskQueue.Enqueue("任务" + i);
        Console.WriteLine("生产:任务" + i);
        Task.Delay(300).Wait();
    }
});

// 消费者线程:从队列取任务
Task.Run(() =>
{
    while (true)
    {
        if (taskQueue.TryDequeue(out string task))
        {
            Console.WriteLine("处理:" + task);
        }
        Task.Delay(200).Wait();
    }
});

Console.ReadLine();
相关推荐
deepin_sir16 小时前
02 - 第一个 Python 程序
开发语言·python
linmengmeng_131416 小时前
【总结】HugeGraph-AI:当图数据库遇见大模型,构建智能图应用的新范式
数据库·人工智能
山上三树16 小时前
协程详细介绍
开发语言
赵钰老师16 小时前
R语言与作物模型(以DSSAT模型为例)融合应用
开发语言·数据分析·r语言
是星辰吖~16 小时前
C++_string类_调用及模拟实现
开发语言·c++
梦想的旅途217 小时前
实现企微外部群主动发送接口:从 0 到 1 实现主动给客户发送的业务实战
java·开发语言·企业微信
是宇写的啊17 小时前
博客系统-小项目
java·数据库·spring boot·mybatis
csdn_aspnet17 小时前
C++ 算法 LeetCode 编号 70 - 爬楼梯
开发语言·c++·算法·leetcode
神仙别闹17 小时前
基于C语言来实现图形界面画板的功能
c语言·开发语言·单片机
xyq202417 小时前
AJAX 简介
开发语言