python模块 queue--同步队列

参考文档:https://docs.python.org/zh-cn/3.8/library/queue.html

  • queue模块实现了多生产者、多消费者队列。特别适用于消息必须安全地在多线程间交换的线程编程。

1、队列类型

  • queue模块实现了三种类型的队列,它们的区别仅仅是条目取回的顺序。
  • 在内部,这三个类型的队列使用锁来临时阻塞竞争线程;然而,它们并未被设计用于线程的重入性处理。

2、queue模块的类和异常

1、class queue.Queue(maxsize=0)

  • 创建先进先出队列(FIFO)对象。
  • Maxsize是一个整数,用于设置可以放置在队列中的元素数量的上限。一旦达到这个大小,插入操作将被阻塞,直到队列中的元素被消耗。
  • 如果maxsize小于或等于0,则队列大小为无穷大。
  • Queue类实现了所有所需的锁定语义

2、class queue.LifoQueue(maxsize=0)

  • 创建后进先出队列(LIFO)对象。
  • maxsize是个整数,用于设置可以放入队列中的元素数的上限。一旦达到这个大小,插入操作将被阻塞,直到队列中的元素被消耗。
  • 如果maxsize小于或等于0,则队列大小为无穷大。

3、class queue.PriorityQueue(maxsize=0)

  • 创建优先级队列对象。
  • Maxsize是一个整数,用于设置可以放置在队列中的元素数量的上限。一旦达到这个大小,插入操作将被阻塞,直到队列中的元素被消耗。
  • 如果maxsize小于或等于0,则队列大小为无穷大。

4、class queue.SimpleQueue

  • 无界的FIFO队列构造函数。简单的队列,缺少任务跟踪等高级功能。(python3.7新功能)

5、exception queue.Empty

  • Queue对象,调用非阻塞的get()(或get_nowait())时,引发的异常。

6、exception queue.Full

  • Queue对象,调用非阻塞的put()(或put_nowait())时,引发的异常。

3、Queue对象的方法

  • 队列对象(Queue,LifoQueue,或者PriorityQueue)的公共方法。

1、Queue.put(item, block=True, timeout=None)

  • 将item放入队列。
  • 有两个可选参数block和timeout。
    • 当block=True(默认)时,插入是阻塞式的,阻塞时间由timeout决定。
      • 如果timeout=None(默认),将一直阻塞,直至有空闲插槽可用;
      • 如果timeout是个正数,将最多阻塞timeout秒,如果在这段时间没有可用的空闲插槽,将引发Full异常
    • 当block=False时,插入是非阻塞式的,即当插入时队列已满将抛出Full异常

2、Queue.get(block=True, timeout=None)

  • 从队列中移除并返回一个元素。
  • 有两个可选参数block和timeout。
    • 当block=True(默认)时,读取是阻塞式的,阻塞时间由timeout决定。
      • 如果timeout=None(默认),将一直阻塞,直至元素可得到;
      • 如果timeout是个正数,将最多阻塞timeout秒,如果在这段时间内元素不能得到,将引发Empty异常
    • 当block=False时,读取是非阻塞式的,即当读取时队列为空将抛出Empty异常

3、Queue.qsize()

  • 返回队列的大致大小。因为队列大小可能被其他线程修改,所以该值为近似值。
  • 注意,qsize() > 0 不保证后续的 get() 不被阻塞,qsize() < maxsize 也不保证 put() 不被阻塞。

4、Queue.empty()

  • 如果队列为空,返回True,否则返回False。
  • 注意,如果empty()返回True,不保证后续调用的put()不被阻塞。如果empty()返回False,也不保证后续调用的get()不被阻塞。

5、Queue.full()

  • 如果队列是满的返回True,否则返回False。
  • 注意,如果full()返回True不保证后续调用的get()不被阻塞。如果full()返回False也不保证后续调用的put()不被阻塞。

6、Queue.put_nowait(item)

  • 相当于put(item, False)。

7、Queue.get_nowait()

  • 相当于get(False)。

8、Queue.task_done()

  • 表示前面排队的元素已经处理完毕。
  • task_done被队列的消费者线程使用
  • 每get()一个元素,就调用task_done()告诉队列,该元素的处理已经完成。
  • 如果Queue.join()当前处于阻塞状态,在所有元素都被处理后,将解除阻塞(这意味着每个已被put()放入队列的元素都会收到task_done()调用)。
  • 如果被调用的次数多于放入队列中的元素数量,将引发 ValueError 异常 。

9、Queue.join()

  • 阻塞至队列中所有的元素都被接收和处理完毕。
  • 当元素添加到队列的时候,未完成任务的计数就会增加。每当消费者线程调用task_done()表示这个元素已经被回收,该元素所有工作已经完成,未完成计数就会减少。当未完成计数降到零的时候,join()阻塞被解除。

4、队列使用示例

1、队列的简单使用

from queue import Queue
q = Queue(5)#如果不设置长度,默认为无限长
q.put('A')
q.put('B')
q.put('C')
print('队列数据数量:', q.qsize())
print('队列是否为空:', q.empty())
print('队列是否已满:', q.full())
print('取数据:', q.get(timeout=1))
print('取数据:', q.get(timeout=1))
print('取数据:', q.get(timeout=1))
print('队列最大长度:', q.maxsize) 

<<<
队列数据数量: 3
队列是否为空: False
队列是否已满: False
取数据: A
取数据: B
取数据: C
队列最大长度: 5

2、task_done()和join()的使用

  • 一般Queue.task_done()和Queue.join()配合使用
  • task_done()的作用:消费者处理一个任务,它就通知生产者我处理了一个任务。
    • 不注释q.task_done()和q.join(),我们发现produce函数在消费者消费完后才结束,而不是生产完就结束。
    • 注释q.task_done()和q.join(),我们发现生产者生产完任务produce函数就结束了,而不是等到消费者消费完才结束。
    • 注释q.task_done(),不注释q.join(),我们发现produce函数一直阻塞没有结束。
import time
from queue import Queue
from threading import Thread, Lock
lock = Lock()
q = Queue()
def produce():
    for i in range(10):
        lock.acquire()
        q.put(i)
        print('生产:', i)
        lock.release()
    print('生产任务完毕!')
    q.join()                        #q.join
    print(produce.__name__, '函数结束!')
def consumer():
    for i in range(10):
        lock.acquire()
        print('消费:', q.get())
        q.task_done()               #q.task_done
        if i == 4:
            print('休息1s...')
            time.sleep(1)           #sleep作用:查看生产者是否阻塞
        lock.release()
    print(consumer.__name__, '函数结束!')
pro = Thread(target=produce)
con = Thread(target=consumer)
pro.start()
con.start()
con.join()
print('消费者任务完成')
pro.join()
print('生产者任务完成')

 

#                                                                                                                  #
posted @ 2021-07-06 12:21  麦恒  阅读(332)  评论(0编辑  收藏  举报