【问题标题】:Quit signal when waiting for blocking read from queue.Queue等待从 queue.Queue 阻塞读取时退出信号
【发布时间】:2019-05-17 09:33:43
【问题描述】:

在许多情况下,我有一个工作线程,它从队列中弹出数据并对其进行操作。在某种事件中,我希望我的工作线程停止。简单的解决方案是在 get 调用中添加 timeout 并在每次 get 时检查 Event/flag超时。然而,这有两个问题:

  • 导致不必要的上下文切换
  • 延迟关闭直到发生超时

有没有更好的方法来监听队列中的停止事件和新数据?是否可以同时收听两个队列并阻塞直到第一个队列中有数据? (在这种情况下,可以使用第二个队列来触发关机。)

我目前使用的解决方案:

from queue import Queue, Empty
from threading import Event, Thread
from time import sleep

def worker(exit_event, queue):
    print("Worker started.")
    while not exit_event.isSet():
        try:
            data = queue.get(timeout=10)
            print("got {}".format(data))
        except Empty:
            pass
    print("Worker quit.")


if __name__ == "__main__":
    exit_event = Event()
    queue = Queue()

    th = Thread(target=worker, args=(exit_event, queue))
    th.start()

    queue.put("Testing")
    queue.put("Hello!")

    sleep(2)

    print("Asking worker to quit")
    exit_event.set()
    th.join()

    print("All done..")

【问题讨论】:

  • 你能把关机信号发送到一个队列吗?我就是这样做的。您能否在队列中发布更结构化的消息,例如 WORK 和 EXIT,然后根据关键字在您的工作分支中发布?您将需要在那里进行一些解析,但如果唯一需要的是检查第一个字节,它应该不会太繁重。
  • 或者,如果您想编写错误代码,请使用退出事件,但在从队列中读取并处理任何数据之前立即检查它,然后将 gobbledygook 发布到那里,因为它将不再被处理- 您只发布数据以使线程从 queue.get() 进行

标签: python multithreading blocking locks


【解决方案1】:

我猜你可以轻松地将timeout 减少到 0.1...0.01 秒。稍有不同的解决方案是使用队列同时向线程发送数据和控制命令:

import queue
import threading
import time

THREADSTOP = 0


class ThreadControl:
    def __init__(self, command):
        self.command = command


def worker(q):
    print("Worker started.")
    while True:
        data = q.get()
        if isinstance(data, ThreadControl):
            if data.command == THREADSTOP:
                break
        print("got {}".format(data))
    print("Worker quit.")


if __name__ == '__main__':

    q = queue.Queue()

    th = threading.Thread(target=worker, args=(q,))
    th.start()

    q.put("Testing")
    q.put("Hello!")

    time.sleep(2)

    print("Asking worker to quit")
    q.put(ThreadControl(command=THREADSTOP))  # sending command

    th.join()

    print("All done..")

另一种选择是使用套接字而不是队列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多