1️⃣ 基础概念与用法
🔹 什么是 Queue?
Queue(队列) 是一种“先进先出”(FIFO — First In, First Out)的数据结构。你可以把它想象成排队买票的队伍:第一个来的排在最前面,最后一个来的排在最后面;服务时也是从最前面开始。
在 C# 中,Queue<T> 是位于 System.Collections.Generic 命名空间中的泛型集合类,用于存储同类型对象的有序集合。
🔹 如何定义一个 Queue?
using System;
using System.Collections.Generic;// 创建一个存储字符串的队列
Queue<string> queue = new Queue<string>();// 或者创建一个存储整数的队列
Queue<int> numberQueue = new Queue<int>();
✅ 小贴士:
T表示泛型类型,你可以替换为任何数据类型(如int,string,Person等)。
🔹 常用方法一览
| 方法名 | 功能说明 | 
|---|---|
| Enqueue(T) | 将元素添加到队列末尾 | 
| Dequeue() | 移除并返回队列开头的元素 | 
| Peek() | 返回队列开头的元素(不移除) | 
| Count | 获取当前队列中元素数量 | 
| Clear() | 清空队列 | 
| Contains(T) | 检查是否包含指定元素 | 
🔹 简单示例:模拟排队买票
using System;
using System.Collections.Generic;class Program
{static void Main(){Queue<string> ticketQueue = new Queue<string>();// 排队入场ticketQueue.Enqueue("张三");ticketQueue.Enqueue("李四");ticketQueue.Enqueue("王五");Console.WriteLine($"当前排队人数:{ticketQueue.Count}");// 开始服务while (ticketQueue.Count > 0){string customer = ticketQueue.Dequeue();Console.WriteLine($"正在服务:{customer}");}Console.WriteLine("所有顾客已服务完毕!");}
}
✅ 输出结果:
当前排队人数:3
正在服务:张三
正在服务:李四
正在服务:王五
所有顾客已服务完毕!
💡 重点记忆:
Enqueue→ 加入队尾
Dequeue→ 取出队头(并移除)
Peek→ 查看队头(不移除)
2️⃣ 进阶知识点
🔹 与其他集合的区别
| 集合类型 | 特点 | 适用场景 | 
|---|---|---|
| Queue<T> | FIFO(先进先出) | 任务调度、消息队列 | 
| Stack<T> | LIFO(后进先出) | 撤销操作、括号匹配 | 
| List<T> | 可随机访问、动态数组 | 需要频繁增删改查 | 
| Dictionary<TKey, TValue> | 键值对存储 | 快速查找、映射关系 | 
🧠 记住口诀:
- Queue → 排队买票 → 先来先服务
- Stack → 压栈弹栈 → 后进先出(像叠盘子)
🔹 性能特点
- 插入(Enqueue) :O(1) —— 非常高效,直接加到尾部。
- 删除(Dequeue) :O(1) —— 直接从头部移除。
- 查找(Contains) :O(n) —— 需要遍历整个队列。
- 访问特定位置元素:不支持直接索引访问(没有 queue[i])。
⚠️ 注意:如果你需要频繁查找或按索引访问元素,建议使用
List<T>而不是Queue<T>。
🔹 线程安全问题
默认的 Queue<T> 不是线程安全的。如果多个线程同时读写同一个队列,可能会导致数据错误或异常。
✅ 解决方案:
- 手动加锁(推荐简单场景):
private static readonly object _lock = new object();lock (_lock)
{queue.Enqueue(item);
}lock (_lock)
{if (queue.Count > 0)item = queue.Dequeue();
}
- 使用线程安全的 ConcurrentQueue<T>(推荐多线程场景):
using System.Collections.Concurrent;ConcurrentQueue<string> threadSafeQueue = new ConcurrentQueue<string>();
threadSafeQueue.Enqueue("用户A");
threadSafeQueue.TryDequeue(out string user); // 安全取出
📌 推荐:在多线程环境中优先使用
ConcurrentQueue<T>,它是专门为并发设计的。
3️⃣ 实际工作中的使用场景
🔹 场景一:任务调度系统
比如一个后台服务需要处理大量用户请求,可以将请求放入队列,由工作线程逐个处理。
Queue<Request> requestQueue = new Queue<Request>();// 用户提交请求
requestQueue.Enqueue(new Request { UserId = 1, Action = "支付" });// 工作线程处理
while (requestQueue.Count > 0)
{var req = requestQueue.Dequeue();ProcessRequest(req);
}
🎯 优点:保证请求按顺序处理,避免资源竞争。
🔹 场景二:消息队列 / 事件总线
在解耦系统模块时,常用队列传递消息或事件。
Queue<EventMessage> eventQueue = new Queue<EventMessage>();// 发布事件
eventQueue.Enqueue(new EventMessage { Type = "UserLogin", Data = "user123" });// 订阅者消费
while (eventQueue.Count > 0)
{var msg = eventQueue.Dequeue();HandleEvent(msg);
}
🔄 适合微服务、插件架构、事件驱动系统。
🔹 场景三:广度优先搜索(BFS)算法
在图或树的遍历中,Queue 是实现 BFS 的核心结构。
Queue<Node> bfsQueue = new Queue<Node>();
bfsQueue.Enqueue(rootNode);while (bfsQueue.Count > 0)
{Node current = bfsQueue.Dequeue();foreach (Node child in current.Children){bfsQueue.Enqueue(child);}
}
🧩 常见于路径查找、社交网络好友推荐、游戏地图寻路等。
🔹 场景四:打印任务队列
打印机管理系统中,多个文档按提交顺序打印。
Queue<Document> printQueue = new Queue<Document>();
printQueue.Enqueue(new Document { Name = "合同.pdf" });
printQueue.Enqueue(new Document { Name = "发票.docx" });while (printQueue.Count > 0)
{var doc = printQueue.Dequeue();PrintDocument(doc);
}
🖨️ 保证打印顺序,避免混乱。
📌 总结与学习建议
✅ 核心要点回顾:
- Queue 是 先进先出 结构,适用于顺序处理场景。
- 主要方法:Enqueue,Dequeue,Peek,Count。
- 不支持索引访问,查找效率低。
- 多线程需使用 ConcurrentQueue<T>或手动加锁。
- 常用于任务调度、消息传递、BFS算法等。
🎯 学习建议:
- 动手写几个小例子,比如模拟银行叫号、订单处理。
- 对比 Stack<T>和Queue<T>,理解不同数据结构的应用差异。
- 在项目中尝试用 ConcurrentQueue<T>替代普通Queue<T>,体验线程安全的好处。
📘 附录:常用方法速查表
Queue<string> q = new Queue<string>();q.Enqueue("A");           // 添加到队尾
q.Dequeue();              // 移除并返回队头元素
q.Peek();                 // 查看队头元素(不移除)
q.Count;                  // 当前元素数量
q.Contains("A");          // 是否包含某元素
q.Clear();                // 清空队列
 有些事情,死了也要做。但有些事情,是死也不能做的。——烽火戏诸侯《剑来》
有些事情,死了也要做。但有些事情,是死也不能做的。——烽火戏诸侯《剑来》