python - 线程无限期挂起

标签 python multithreading

我在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()),它仍然挂起,但我不确定为什么。

问题:

  1. 为什么会挂起?
  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

关于python - 线程无限期挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50202170/

相关文章:

c++ - 从 C++ 调用 Cython 函数

Python 3.6 - 变量值可以用作字典中键值的一部分吗?

Python SSL 和 Unicode 域

java - 尝试同步两个线程时遇到问题

python - 从 .jpg 文件创建大量按钮图像

python - 模拟函数以引发异常以测试 except block

Android 活跃下载线程

c# - 如何以线程安全的方式使用多线程的 async/await 异步写入文件流

java - 用于从 MySQL 数据库获取信息的 AsyncTask 与工作线程

python - word2vec tensorflow 中的执行流程