转载请注明出处:https://blog.csdn.net/jinixin/article/details/80174328
概述
Queue模块,顾名思义其实现了各种队列,比如Queue,LifoQueue与PriorityQueue。
一开始我没有过多注意到该模块,随着学习深入,多线程编程越来越普遍,常常需要共享数据,而数据在共享时一旦涉及修改,就需要加锁来确保某个时刻仅有一个线程可以修改数据。
由于Queue模块是线程安全的, 故数据可以通过其来实现共享, 比起使用锁和信号量着实方便不少. 请注意该模块仅能在多线程环境中共享数据, 如果想在多进程环境中共享数据, 请使用multiprocessing.Queue模块.
构造方法
Queue模块中有三种顺序表,分别是Queue,LifoQueue与PriorityQueue,下面是他们对应的构造方法:
三个构造方法都有maxsize参数,表示容量。当向已满的队列中继续插入时,将引起程序阻塞或异常。当maxsize小于等于0时,表示该队列容量无上限。
Queue(maxsize=0)
队列,先入先出
LifoQueue(maxsize=0)
栈,先入后出
PriorityQueue(maxsize=0)
优先队列
优先队列中的元素为item,取出元素时item先按"sorted(list(item))[0])"排序,再将第一个item弹出队列。
队列中item可以是自定义类型,但别忘记在自定义类型中实现__cmp__或__lt__方法。
优先队列的例子:
#!/usr/bin/env python3
# coding=utf-8
from queue import PriorityQueue
def main():
q = PriorityQueue(5)
q.put([3, '满月'])
q.put([1, '繁星'])
q.put([4, '江上'])
print(q.get(), q.get(), q.get())
q = PriorityQueue(5)
q.put(3)
q.put(1)
q.put(4)
print(q.get(), q.get(), q.get())
if __name__ == '__main__':
main()
结果:
常用方法
qsize()
返回目前队列中元素的数量
empty()
队列是否为空
full()
队列是否已满
put(item, block=True, timeout=None)
向队列中插入item
如果队列已满,且block为True时,则在timeout秒数内阻塞,等待插入;当block为False或等待超过timeout时,抛出queue.Full异常。
如果队列已满,block为True,且timeout为None时,程序会一直阻塞直至成功插入元素。
put_nowait(item)
等价于put(item, block=False)
get(block=True, timeout=None)
从队列中取得下一个元素
如果队列为空,且block为True时,则在timeout秒数内阻塞,等待获取;当block为False或等待超过timeout时,抛出queue.Empty异常。
如果队列为空,block为True,且timeout为None时,程序会一直阻塞直至成功获取下一个元素。
get_nowait()
等价于get(block=False)
task_done()
告诉队列,之前的一次任务已完成
get()从队列中弹出并返回一个元素,该元素再被用于一系列可能的操作后,task_done()用于告诉队列这一系列操作成功执行完成。
如果在每次get()之后不调用task_done(),则之后join()方法会一直阻塞程序。
如果不使用join(),那么task_done()不需要调用。
join()
阻塞程序,直到队列中所有任务都完成,需和task_done()配合使用
代码
使用Queue模块的Queue队列,实现生产者与消费者:
#!/usr/bin/env python3
# coding=utf-8
import time
from threading import Thread
from queue import Queue, LifoQueue
def consumer(index, q):
while True:
if q.empty():
break
sleep_time = q.get(block=True, timeout=10) # 弹出并返回
print('%s thread sleep for %s seconds' % (index, sleep_time))
time.sleep(sleep_time)
q.task_done() # 通知队列上一个get返回元素的任务已完成
print('%s thread finished' % index)
def producer(q):
for sleep_time in range(20): # 将休眠时间压入队列
q.put(sleep_time, block=True, timeout=20)
def main(q):
thread_list = []
for index in range(5):
if index == 0:
t = Thread(target=producer, args=(q,)) # 生产者
else:
t = Thread(target=consumer, args=(index, q)) # 消费者
t.start() # 开始该子线程
thread_list.append(t)
q.join() # 等待队列为空,注意task_done方法必须被调用,否则一直阻塞
for thread in thread_list: # 等待所有子线程全部结束
thread.join()
print('done')
if __name__ == '__main__':
q = Queue(5)
# q = LifoQueue(5)
main(q)
结果:
参考链接:
https://docs.python.org/3/library/queue.html
文中如有不当之处,还望包容和指出,感谢