我在Python documentation中阅读了有关队列
的内容和 this book ,而且我不完全明白为什么我的线程挂起。我有以下mcve :
from threading import Thread
import queue
def print_number(number_queue_display):
while True:
number = number_queue_display.get()
print(number)
number_queue_display.task_done()
number_queue = queue.Queue()
printing_numbers = Thread(target=print_number, args=(number_queue,),)
printing_numbers.start()
number_queue.put(5)
number_queue.put(10)
number_queue.put(15)
number_queue.put(20)
number_queue.join()
printing_numbers.join()
唯一有效的时候是我将线程设置为守护进程,如下所示:
printing_numbers.setDaemon(True)
但那是因为正如 Python 文档中所述,the program will exit当只剩下守护线程时。 Queue
的 Python 文档示例不使用守护线程。
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left.
即使我删除了两个连接(number_queue.join()
printing_numbers.join()
),它仍然挂起,但我不确定为什么。
问题:
- 为什么会挂起?
- 如何将其保留为非守护线程,但防止其挂起?
最佳答案
print_number()
正在运行无限循环 - 它永远不会退出,因此线程永远不会结束。它永远位于 number_queue_display.get()
中,等待另一个永远不会出现的队列项。然后,由于线程永远不会结束,printing_numbers.join()
也会永远等待。
所以你需要某种方法来告诉线程退出。一种常见的方法是将一个特殊的“哨兵”值放入队列中,并在看到该值时让线程退出。具体而言,这是一个完整的程序,它与您开始时的程序非常相似。 None
用作哨兵(并且通常用于此目的),但任何唯一的对象都可以工作。请注意,.task_done()
部分已被删除,因为它们不再起作用。
from threading import Thread
import queue
def print_number(number_queue_display):
while True:
number = number_queue_display.get()
if number is None:
break
print(number)
number_queue = queue.Queue()
printing_numbers = Thread(target=print_number, args=(number_queue,),)
printing_numbers.start()
number_queue.put(5)
number_queue.put(10)
number_queue.put(15)
number_queue.put(20)
number_queue.put(None) # tell the thread it's done
printing_numbers.join() # wait for the thread to exit
关于python - 线程无限期挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50202170/