代码之家  ›  专栏  ›  技术社区  ›  intuited

通信队列结束

  •  8
  • intuited  · 技术社区  · 14 年前

    我正在学习使用队列模块,对于如何让队列使用者线程知道队列是完整的,我有点困惑。理想情况下我想用 get() 如果队列被标记为“done”,则让它抛出异常。有没有比附加一个sentinel值来标记队列中的最后一个项目更好的方法来进行通信?

    5 回复  |  直到 14 年前
        1
  •  12
  •   Community CDub    7 年前

    原始(大部分已更改;请参阅下面的更新)

    基于一些 suggestions (谢谢!)属于 Glenn Maynard Queue.Queue 实现了 close module CloseableQueue 阶级与社会 Closed 异常类。我计划将它扩展到包括 Queue.LifoQueue Queue.PriorityQueue .

    这个 可关闭队列 put s、 但不妨碍未来 get 直到队列清空。这对我来说是最有意义的;清除队列的功能似乎可以作为一个单独的mixin*添加,它与closeability功能正交。所以基本上 ,通过关闭队列,表示最后一个元素已被删除 last=True 进入决赛 ,以及随后对 一旦队列清空,以及与这些描述匹配的未完成的阻塞呼叫,将引发 关闭 例外。

    这对于单个生产者为一个或多个消费者生成数据的情况非常有用,但对于消费者等待特定项目或项目集的多重安排也非常有用。特别是它没有提供一种方法来确定所有的生产商都已经完成了生产。要实现这一目标,就必须提供某种方式来登记生产者( .open() ?),以及一种表明生产者注册本身已关闭的方式。

    Queue.get Queue.put 并且添加了 关闭 closed 方法。

    __enter__ __exit__ 方法;否则,contextlib closing 函数应适用于CloseableQueue实例。

    *:在这里,我松散地使用术语“mixin”。作为 Queue

    CloseableQueue 模块现在提供 CloseableLifoQueue CloseablePriorityQueue 班级。我还添加了一些方便的函数来支持迭代。仍然需要把它作为一个合适的包进行返工。有一个类工厂函数可以方便地对其他类进行子类化 -派生类。

    更新2

    可关闭队列 现在可通过 PyPI

    $ easy_install CloseableQueue
    

    评论和批评是受欢迎的,特别是来自这个答案的匿名选民。

        3
  •  7
  •   Glenn Maynard    14 年前

    哨兵是关闭队列的一种自然方式,但有几件事需要注意。

    首先,记住您可能有多个消费者,因此您需要为每个正在运行的消费者发送一次sentinel,并保证每个消费者只消耗一个sentinel,以确保每个消费者收到其关机sentinel。

    第二,记住Queue定义了一个接口,如果可能,代码的行为应该与底层队列无关。您可能有一个PriorityQueue,或者可能有其他类公开同一接口并以其他顺序返回值。

    不幸的是,很难同时处理这两个问题。为了处理不同队列的一般情况,正在关闭的使用者必须在接收到其shutdown sentinel之后继续使用值,直到队列为空。这意味着它可能会消耗另一个线程的哨兵。这是队列接口的一个弱点:它应该有一个 Queue.shutdown 调用以导致所有使用者抛出异常,但缺少该异常。

    因此,在实践中:

    • 如果您可能正在使用PriorityQueue,请确保sentinel具有最低优先级。
        4
  •  2
  •   GJ.    14 年前

    1. 发送到API:等待事件(如队列中的新消息)。

    如果您不希望使用者线程在作业完成后终止,则将sentinel值放入队列以终止任务。

        5
  •  0
  •   radman    14 年前

    您的建议是:检查队列以查看是否定期执行,这是非常不可取的。轮询是多线程编程中的反模式,您应该始终使用通知。

    编辑: