Python Queue模块知识点详解
面向编程小白的通俗易懂解释
什么是队列?
队列就像现实生活中的排队,先来的先服务,后来的在后面等。在编程中,队列是一种先进先出(FIFO)的数据结构。
大白话解释: 想象你在银行排队办理业务,第一个来的人第一个被服务,新来的人只能排在队伍末尾。
为什么使用队列?
- 任务调度: 管理需要按顺序执行的任务
- 缓冲数据: 当生产数据的速度快于消费速度时
- 多线程通信: 线程之间安全地传递数据
- 解耦系统: 让生产者和消费者不需要相互等待
Queue模块基础
Python的queue
模块提供了线程安全的队列实现,特别适合多线程编程。
导入模块
import queue
三种队列类型
- Queue: 标准先进先出(FIFO)队列
- LifoQueue: 后进先出(LIFO)队列,类似栈
- PriorityQueue: 优先级队列,优先级高的先出
创建队列
# 创建普通队列
q = queue.Queue(maxsize=10) # 设置最大容量为10
# 创建LIFO队列(栈)
lq = queue.LifoQueue()
# 创建优先级队列
pq = queue.PriorityQueue()
q = queue.Queue(maxsize=10) # 设置最大容量为10
# 创建LIFO队列(栈)
lq = queue.LifoQueue()
# 创建优先级队列
pq = queue.PriorityQueue()
队列基本操作
队列的核心操作只有三个:添加、取出和查看大小
添加元素 – put()
q.put(item) # 将元素放入队列
如果队列满了,默认会阻塞等待直到有空间
获取元素 – get()
item = q.get() # 从队列取出元素
如果队列为空,默认会阻塞等待直到有元素
队列大小
size = q.qsize() # 获取队列当前元素数量
empty = q.empty() # 检查队列是否为空
full = q.full() # 检查队列是否已满
empty = q.empty() # 检查队列是否为空
full = q.full() # 检查队列是否已满
高级队列操作
除了基本操作,队列还提供了一些高级功能
任务完成通知
# 通知队列所有任务已完成
q.task_done()
# 阻塞等待所有任务完成
q.join()
q.task_done()
# 阻塞等待所有任务完成
q.join()
常用于生产者-消费者模式中协调线程
非阻塞操作
try:
item = q.get_nowait() # 不阻塞,队列为空时抛出异常
except queue.Empty:
print(“队列是空的”)
try:
q.put_nowait(item) # 不阻塞,队列满时抛出异常
except queue.Full:
print(“队列已满”)
item = q.get_nowait() # 不阻塞,队列为空时抛出异常
except queue.Empty:
print(“队列是空的”)
try:
q.put_nowait(item) # 不阻塞,队列满时抛出异常
except queue.Full:
print(“队列已满”)
队列类型比较
三种队列类型的不同行为特点
Queue – 普通队列
- 最先放入的元素最先取出
- 就像排队买票
LifoQueue – 栈队列
- 最后放入的元素最先取出
- 就像叠盘子,只能取最上面的
PriorityQueue – 优先级队列
- 元素按优先级顺序取出
- 优先级由元组 (priority, data) 决定
- 数字越小优先级越高
- 相同优先级按插入顺序
使用场景示例
队列在实际编程中的常见应用
多线程任务处理
import threading
def worker(q):
while True:
item = q.get()
print(f”处理任务: {item}”)
q.task_done()
q = queue.Queue()
# 创建4个工作线程
for i in range(4):
t = threading.Thread(target=worker, args=(q,))
t.daemon = True
t.start()
# 添加10个任务
for item in range(10):
q.put(item)
# 等待所有任务完成
q.join()
def worker(q):
while True:
item = q.get()
print(f”处理任务: {item}”)
q.task_done()
q = queue.Queue()
# 创建4个工作线程
for i in range(4):
t = threading.Thread(target=worker, args=(q,))
t.daemon = True
t.start()
# 添加10个任务
for item in range(10):
q.put(item)
# 等待所有任务完成
q.join()
FIFO队列 (先进先出)
1
2
3
新元素添加到队尾,总是从队头取出元素
LIFO队列 (后进先出)
3
2
1
新元素添加到顶部,总是取出最新添加的元素
队列方法快速参考表
方法 | 描述 | 返回值/行为 |
---|---|---|
q.put(item) | 将元素放入队列 | 阻塞如果队列满 |
q.get() | 从队列取出元素 | 阻塞如果队列空 |
q.qsize() | 返回队列大小 | 近似值(多线程下) |
q.empty() | 检查队列是否空 | True/False(多线程下不可靠) |
q.full() | 检查队列是否满 | True/False(多线程下不可靠) |
q.task_done() | 通知任务已完成 | 配合join()使用 |
q.join() | 阻塞直到所有任务完成 | 等待所有task_done()调用 |
q.put_nowait(item) | 非阻塞添加 | 队列满时抛出Full异常 |
q.get_nowait() | 非阻塞获取 | 队列空时抛出Empty异常 |
使用注意事项
- 线程安全: queue模块是线程安全的,可在多线程环境中直接使用
- 队列大小: 设置maxsize防止内存耗尽,0表示无限大
- 阻塞行为: get()和put()默认会阻塞,可用block=False或timeout参数控制
- 优先级队列: 元素必须是(priority_number, data)格式,priority_number通常为整数
- 空队列检查: 多线程环境中,empty()的结果可能不可靠
- 任务跟踪: task_done()和join()用于跟踪任务完成情况
给编程小白的建议: 当你需要在多个线程之间传递数据,或者需要控制任务执行顺序时,queue模块是你的好帮手。它处理了所有复杂的线程同步问题,让你可以专注于业务逻辑。