我正在阅读Python documentation和this book中的Queue
,我并不完全理解为什么我的帖子会挂起。我有以下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文档示例不使用守护程序线程。
线程可以标记为“守护程序线程”。这个的意义 flag是只有守护进程线程时整个Python程序退出 离开了。
即使我要删除这两个联接(number_queue.join()
printing_numbers.join()
),它仍然会挂起,但我不确定原因。
问题:
答案 0 :(得分:2)
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