问题描述
如何检查队列是否为空?运行以下代码:
from multiprocessing import Queue
q = Queue()
print(q.empty())
q.put("a")
print(q.empty())
渲染:
True
True
添加元素后,q.empty()
是否应该返回False
?
解决方法
两种可能的解决方案:
- 使用
queue.Queue
代替multiprocessing.Queue
: 它们之间有一些differences in doc:
它们的区别在于Queue缺少Python 2.5的queue.Queue类中引入的task_done()和join()方法。
from queue import Queue
q = Queue()
print(q.empty())
q.put("a")
print(q.empty())
- 或者就像@Hans Musgrave在评论中说的那样。
time.sleep(1)
不能得到保证。您可以改用time.sleep(0)
:
from multiprocessing import Queue
import time
q = Queue()
print(q.empty())
time.sleep(0)
q.put("a")
print(q.empty())
所有人都给我
True
False
关于为什么sleep(0)
,值为零会导致线程将其时间片的剩余部分交还给准备运行的任何其他线程。如果没有其他线程可以运行,该函数将立即返回,并且线程将继续执行
cpu放弃了执行q.emety()
任务的资源。这就是我的想法。
稳定的方法是使用queue.Queue
或queues.SimpleQueue
。
官方推荐的解决方案是使用Manager.Queue
。
从Python docs引用:
,注意:
将对象放入队列时,将对对象进行酸洗,然后后台线程将酸洗的数据刷新到基础管道。这会带来一些令人惊讶的后果,但不会造成任何实际困难-如果它们确实困扰您,那么您可以使用由经理创建的队列。
1.将对象放入空队列后,队列的empty()方法返回False之前,可能会有无穷的延迟,而get_nowait()可以在不提高Queue.Empty的情况下返回。
2.如果多个进程正在排队对象,则可能在另一端乱序接收对象。但是,通过相同过程排队的对象将始终相对于彼此按预期顺序排列。
put
方法是异步的,因此在检查元素时队列可以仍然为空。在time.sleep(1)
和put
之后加上empty()
将返回False
。