队列Queue

Python中队列实现了线程安全,即在多线程对同一个队列进行操作时候,线程会独占资源直到这个线程释放,在线程独占资源这个过程中其他线程无法对该队列进行操作。

queue

form queue import Queue

q = Queue()             #  实例化一个队列,q = Queue(size=None)

q.put(3)                # 放入一个元素
elem = q.get()          # 取出一个元素

print(q.empty(), q.qsize)   # 显示是否为空 和 当前元素个数
# 当queue中的元素满了再进行put操作,或者queue中元素为空时进行get操作时,程序会一直阻塞。
elem = q.get()    # 此时程序会一直阻塞。可以设置等待时间

elem = q.get(block=True, timeout=10)  # 阻塞10秒,拿到数据继续执行,拿不到数据报错。

block 参数指定该次取值是阻塞的,设置为False表示不阻塞,没有数据直接报错,也可以使用q. get_nowait(),默认调用get(block=False)

queue中提供了常用的方法如下

__init__(maxsize:int)
 _init(maxsize)
 empty()
 full()
 get(block, timeout)
 get_nowait()
 put(item, block, timeout)
 put_nowait(item)
 qsize()
 join()
 task_done()

PriortyQueue(优先队列)

优先队列和queue有些许的差别。它的底层使用堆数据结构来进行处理。

优先队列顾名思义可以根据消息的等级实现消息选择性的弹出,每次取出的值为所有数据中优先级最高的那个数据,也就会这个堆的堆顶元素

from queue import PriorityQueue

q = PriorityQueue()

q.put(10)
q.put(5)
q.put(9)

while not q.empty():
    print(q.get(), end=",")

====输出结果=====
5,9,10

默认每次将“值”最小的元素优先返回,注意:堆中的第一个元素输出后,将最后一个元素置顶,再进行堆调整(queue和LIFOqueue不需要),调整的过程中涉及两个元素之间的大小比较,所以这些数据的数据类型必须可以两两大小比较。否则将会报错。

 queue的线程安全误区

上面的代码在单线程中是安全的,但是在线程中使用会出现问题,问题在于

while not q.empty:
    q.get()          # 当只剩下最后一个元素,多个线程同时通过了not empty判断并未取值,然后在取值的时候,未必还有元素,此时线程就阻塞了。
 

文章一开始说的线程安全是指,在一次操作queue时,保证了只有一条线程操作。比如get,put,qsize,empty等单次操作。模块内部会使用锁的机制来保证线程安全,进入前加锁,操作结束时解锁。

原文地址:https://www.cnblogs.com/k5210202/p/13067979.html