【发布时间】:2021-02-23 08:13:03
【问题描述】:
在我的一个 asyncio 项目中,我经常使用一种同步方法,并且想知道它是否是某种标准工具,我可以给 google 提供一个名称以了解更多信息。我使用术语“1-item queue”只是因为我没有更好的名字。这是一个降级队列,与Queue(maxsize=1) 无关。
# [controller] ---- commands ---> [worker]
控制器向worker发送命令(queue.put,实际上是put_nowait),worker等待它们(queue.get)并执行它们,但特殊规则是唯一的最后一个命令是重要且立即的替换之前所有未完成的命令。因此,队列中等待执行的命令永远不会超过 1 个。
为了实现这一点,控制器在放置之前清除队列。没有queue.clear,所以它必须丢弃(和get_nowait)等待的项目,如果有的话。 (queue.clear 的缺席让我产生了这个疑问。)
在工作人员方面,如果命令执行需要休眠,则将其替换为带有超时的newcmd=queue.get。当超时发生时,它是睡眠;当get 成功时,当前工作中止并开始执行newcmd。
【问题讨论】:
-
听起来队列不是您的用例的原语,尽管您以某种方式使其工作。我会用一对
asyncio.Event来实现这种同步,我会在上面附加你需要运行的命令。这样你就不需要清除任何东西,只需分配新的命令就可以了。 -
@user4815162342 你能写更多关于这对事件的细节吗?对不起,我没明白你的意思。
-
抱歉,“对”是编辑留下的,指的是(事件,命令)对,命令是您现在放入队列的对象。后来我想到你可以将命令附加到事件中(使用普通的赋值,
event.my_command = ...,所以你不需要随身携带两个物体。这有帮助吗? -
@user4815162342 让我们看看。控制器设置
my_commandattr 并调用event.set。工作人员 - 当被唤醒时 - 获取命令并调用event.clear。是的,我认为这应该有效。Event是一个更简单的概念,但不解决数据交换,必须附加命令。 OTOH aQueue传输数据,但必须以不寻常的方式使用。不知道我是否应该改变我的程序,但你的想法帮助我从另一个角度看待这个问题。谢谢。 -
正确,这正是我的想法。您实际上并不需要一个队列,只需要一个唤醒机制和一个用于将单个对象附加到唤醒的单元(最新命令)。 Event 是 asyncio 中最简单的多用途唤醒设备(也有条件,但它增加了您根本不需要的多线程的复杂性)。如果你使用事件,不要忘记在
event.wait()之后立即从工作人员调用event.clear(),否则事件将保持设置。不要担心竞争条件,因为协程无法在等待之间切换。
标签: python python-asyncio computer-science