python中 小编了解的总共有三种队列 分别是fifo先进先出 还有lifo先进后出 其次还有priority优先级的队列(数字越小 优先级别越高)
下面小编就给大家分别介绍一下三种队列的用法 和一些注意情况
一 fifo队列 也叫先进先出队列 意思是 先放进队列的 会优先出去进行消费 比如 看下方代码
import queue as myqueue
"""fifo 先进先出队列"""
fifo_queue = myqueue.Queue(-1) # 如果设置小于0 则代表队列无限长 如果设置大于0则代表队列有限
fifo_queue.put("1")
fifo_queue.put("2")
fifo_queue.put("3")
print(fifo_queue.get())
print(fifo_queue.get())
print(fifo_queue.get())
输出结果为
这里小编定义了一个队列 首先使用队列的put方法 往这个队列里面分别填充了 字符串 1,2,3 然后使用队列的get方法 进行取值,最后 输出结果分别是1,2,3也就满足了一开始我们所说的 首先放进去的数据 是会最先取出来。
了解到基本的情况之后 小编把原来的代码修改了一下
# @message 队列 fifo先进先出 lifo后进先出 priority优先级的队列(数字越小 优先级越高)
import queue as myqueue
"""fifo 先进先出队列"""
fifo_queue = myqueue.Queue(2) # 如果设置小于0 则代表队列无限长 如果设置大于0则代表队列有限
fifo_queue.put("1")
fifo_queue.put("2")
fifo_queue.put("3")
print(fifo_queue.get())
print(fifo_queue.get())
print(fifo_queue.get())
然后运行结果
what? 也就改了一下队列的空间大小 怎么就直接没有东西输出了?通过定位 我们可以看到是执行代码 fifo_queue.put("3")进入了死循环,当然这个我们也可以叫做阻塞,好 既然这样 我们看一下这个方法的源代码
def put(self, item, block=True, timeout=None):
'''Put an item into the queue.
If optional args 'block' is true and 'timeout' is None (the default),
block if necessary until a free slot is available. If 'timeout' is
a non-negative number, it blocks at most 'timeout' seconds and raises
the Full exception if no free slot was available within that time.
Otherwise ('block' is false), put an item on the queue if a free slot
is immediately available, else raise the Full exception ('timeout'
is ignored in that case).
'''
with self.not_full:
if self.maxsize > 0:
if not block:
if self._qsize() >= self.maxsize:
raise Full
elif timeout is None:
while self._qsize() >= self.maxsize:
self.not_full.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = time() + timeout
while self._qsize() >= self.maxsize:
remaining = endtime - time()
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify()
从这个函数的说明我们可以了解到 他有二个参数 block是控制是否阻塞,timeout是超时时间,也就是说 我们默认是以阻塞的方式将值进行写入队列的,由于我们一开始设置的队列大小是2 但是你追加了三个值,所以当你追加第三个值的时候队列已经满了 同时你的超时时间又没有设置 他就会一直等待下去 就形成了我们所说的死循环 ,也就是阻塞(除非这个时候 有另外的线程在消费这个队列,否则当前线程会一直阻塞下去)
好吧 既然没有超时时间 那么我就添加超时时间 :
由于是put数字3进行阻塞的 小编这里就偷个懒 只把添加数字3的时候 传个超时时间 于是代码就变成了如下
import queue as myqueue
"""fifo 先进先出队列"""
fifo_queue = myqueue.Queue(2) # 如果设置小于0 则代表队列无限长 如果设置大于0则代表队列有限
fifo_queue.put("1")
fifo_queue.put("2")
fifo_queue.put("3", timeout=3)
print(fifo_queue.get())
print(fifo_queue.get())
print(fifo_queue.get())
运行结果
what 报错了? 这个异常可以看的出来 当我们加了队列写入数据超时时间的时候 如果队列满了 会引发 queue.Full异常。
既然block默认值是true 那么我们改成传block=False呢(也就是不是阻塞的方式写入)
修改源代码成
import queue as myqueue
"""fifo 先进先出队列"""
fifo_queue = myqueue.Queue(2) # 如果设置小于0 则代表队列无限长 如果设置大于0则代表队列有限
fifo_queue.put("1")
fifo_queue.put("2")
fifo_queue.put("3", block=False)
print(fifo_queue.get())
print(fifo_queue.get())
print(fifo_queue.get())
当然我们运行结果 跟上面的一致 也是报 queue.Full异常。
了解到put函数之后,我们下面到get函数也是一样,也有block和timeout这二个参数,但是他们原理相似
结论:
put方法
阻塞方式:不会引发异常,但是当队列满了并且没有设置超时时间的时候 当前线程会一直进行阻塞。直到有另外的线程对其消费,才会继续写入。
非阻塞方式:当队列满了 会引发 queue.Ful异常。
get方法:
阻塞方式:不会引发异常,但是队列没值并且没有设置超时时间的时候 当前线程会一直进行阻塞,直到有其他的线程对这个队列进行写入数据,当前线程才会开始消费
非阻塞方式:当队列为空的时候 会引发 Queue.Empty异常
二 lifo队列 也就是先进后出队列 跟lifi刚好相反
import queue as myqueue """lifo先进后出""" lifo_queue = myqueue.LifoQueue(-1) lifo_queue.put("1") lifo_queue.put("2") lifo_queue.put("3") print(lifo_queue.get()) print(lifo_queue.get()) print(lifo_queue.get())
输出结果
当然他的是否阻塞和超时时间跟fifo的一样 。
三 priority队列,优先级的队列(数字越小 优先级别越高)
import queue as myqueue """ priority优先级别的队列""" priority_queue = myqueue.PriorityQueue() priority_queue.put((2, "two")) priority_queue.put((3, "two")) priority_queue.put((1, "one")) print(priority_queue.get()) print(priority_queue.get()) print(priority_queue.get())
输出结果
这里 数字越小的 会在前面先取出来,而不管追加的顺序。
当然你可能会问 假设数字是一样的呢? 小编经过几次测试之后 ,发现当数字相同当时候 会看第二个参数的长度 如果长度越短 就会越先输出 比如
import queue as myqueue """ priority优先级别的队列""" priority_queue = myqueue.PriorityQueue() priority_queue.put((2, "o")) priority_queue.put((2, "ooo")) priority_queue.put((2, "o")) print(priority_queue.get()) print(priority_queue.get()) print(priority_queue.get())
输出结果
测试代码
import queue as myqueue """ priority优先级别的队列""" priority_queue = myqueue.PriorityQueue() priority_queue.put((2, [1, 2, 3])) priority_queue.put((2, [1])) priority_queue.put((2, [1, 2, 3, 4])) print(priority_queue.get()) print(priority_queue.get()) print(priority_queue.get())
输出结果
当然如果你的值不是同种类型的时候 我们就暂时不考虑了 。。。