如何停止守护线程?

14

我有一个简单的生产者消费者应用程序。

生产者是一个线程,它将数据写入队列,而消费者是一个线程,它从队列中读取消息并执行某些操作,在某些时候退出。

我的生产者代码看起来有点像这样:

def producer(queue):
    while not queue.full():
        queue.put(randint(1, 199))

以及消费者

def consumer(queue):
    for i in range(100):
        print(queue.get())
        queue.task_done()

在我的主函数中,我像这样调用那些线程:

p = Thread(target=producer)
c = Thread(target=consumer)

p.daemon = True
p.start()
c.start()
c.join()

c结束时,唯一剩余的非守护线程是主线程,正确的方式是结束这些线程?

更新

这是我的生产者正在使用的确切代码,因为消费者正在退出并且问题出现在生产者身上。

def generate_random_alphanumerics(msg_queue):
    while True:
        if not msg_queue.full():
            msg_queue.put(hashlib.sha1(bytes(randint(1, 10000))).hexdigest() * 10)
        else:
            sleep(0.01)

线程休眠是问题所在吗?


2
您不必停止守护线程。当主线程结束时,它们将自动终止。请参见我的这个答案,以获取更详细的解释。 - martineau
但是程序仍然卡住,而不是退出。 - LetsPlayYahtzee
1
即使我添加了 sys.exit(),这其实是不必要的。 - LetsPlayYahtzee
1
@LetsPlayYahtzee:我怀疑你可能省略了代码的关键部分。如果在启动线程之前将线程正确设置为“守护进程”,则无需特殊的扭曲即可退出。 - ShadowRanger
LetsPlayYahtzee:不,你不应该需要显式调用sys.execit()。你问题中的示例代码可能并不准确地代表了你真正的代码。请在阅读如何创建一个最小、完整和可验证的示例后进行[编辑]。 - martineau
1个回答

34

问题在于生产者循环永远不会结束,因此你需要一种方法告诉它停止。

stop_event= threading.Event()
p = Thread(target=producer, args=(msg_queue, stop_event))
p.start()

制片人变成了:

def generate_random_alphanumerics(msg_queue, stop_event):
    while not stop_event.is_set():
        if not msg_queue.full():
            [...]

然后,当你想停止生产者时,只需执行以下操作:

stop_event.set()

2
好的答案,我一定是瞎了或者这在任何地方都没有以如此简单的方式提到。 - LetsPlayYahtzee
1
这绝对是在 SO 上停止线程的最简单方法。 - Sam Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接