Python 队列
一、分类
1. Queue
标准队列,先进先出(FIFO),队尾插入,队头取元素。
2. LifoQueue
后进先出(first in last out)。与栈的类似
3. PriorityQueue
优先级队列,队列内的元素有次序之分,优先级越大,排队时间越短
二、常用方法
1. put(item[, block[, timeout]])
往队列中放数据,
- 如果可选的参数block为True且timeout为空对象(默认的情况,阻塞调用,无超时)。
- 如果timeout是个正整数,阻塞调用进程最多timeout秒,如果一直无空空间可用,抛出Full异常(带超时的阻塞调用)。
- 如果block为False,如果有空闲空间可用将数据放入队列,否则立即抛出Full异常
- 其非阻塞版本为put_nowait等同于put(item, False)
2. get([block[, timeout]])
从队列中移除并返回一个数据。block 跟 timeout 参数同put方法
其非阻塞方法为 get_nowait()
相当与 get(False)
3. task_done()
意味着之前入队的一个任务已经完成。由队列的消费者线程调用。每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。
如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。
4. join()
阻塞调用线程,直到队列中的所有任务被处理掉。
只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。
三、应用场景
1. 背景
某 Python 系统中,某一时间需要处理批量的大文件,IO吞吐增大,且需要把数据传回 Java 后端系统,但是因为网络传输压力太大,导致网络连接常常摆烂,想着使用队列缓解一下压力。
2. 实现代码
使用哪种队列不是重点,代码实现逻辑都是一样的,只是消费顺序不一样罢了
import threading
import queue
import time
import datetime
upload_queue = queue.Queue(maxsize=2 << 9)
def producer():
"""
模拟生成需要处理的数据
:return:
"""
count = 1
while True:
msg = "消息编号:{}".format(count)
upload_queue.put(msg)
count += 1
if count % 10 == 0:
print("即将睡眠 10 s")
time.sleep(10)
def consumer():
"""
队列消费者,逐条消费
:return:
"""
while True:
msg = upload_queue.get()
print(datetime.datetime.today())
print("上传队列中有消息个数:{}".format(upload_queue.qsize()))
print("接收到 =====>>>>> {}".format(msg))
time.sleep(1)
upload_queue.task_done()
if __name__ == '__main__':
# 设置线程,让他们之间形成生产 - 消费的闭环
t1 = threading.Thread(target=producer, args=[])
t1.start()
t2 = threading.Thread(target=consumer, args=[])
t2.start()