在Python文档中 它说:

一个线程可以被标记为“守护线程”。这其中的意义 标志表示当只有守护进程线程时,整个Python程序退出 是离开了。初始值继承自创建的线程。

有人对这意味着什么有更清楚的解释吗?或者有一个实际的例子说明在哪里将线程设置为守护线程?

澄清它为我:所以唯一的情况下,你不会设置线程为守护进程,是当你想让他们继续运行后,主线程退出?


有些线程执行后台任务,比如发送keepalive包,或执行定期垃圾收集,等等。这些线程只在主程序运行时有用,并且可以在其他非守护进程线程退出后将它们删除。

如果没有守护线程,您必须跟踪它们,并在程序完全退出之前告诉它们退出。通过将它们设置为守护线程,您可以让它们运行并忘记它们,当您的程序退出时,任何守护线程都会自动被杀死。


假设您正在制作某种仪表板小部件。作为此功能的一部分,您希望它在电子邮件框中显示未读邮件计数。所以你做了一个小线,它将:

连接到邮件服务器并询问有多少未读邮件。 用更新后的计数向GUI发出信号。 睡一会儿。

当您的小部件启动时,它将创建这个线程,将其指定为守护进程,然后启动它。因为它是一个守护进程,你不需要考虑它;当您的小部件退出时,线程将自动停止。


也许可以用一种更简单的方式来考虑:当main返回时,如果有非守护进程线程仍在运行,则您的进程将不会退出。

一点建议:当涉及线程和同步时,干净关机很容易出错——如果可以避免,就这样做。尽可能使用守护线程。


其他帖子给出了一些使用守护进程线程的示例。然而,我的建议是永远不要使用它们。

这并不是因为它们没有用处,而是因为如果你使用它们,你会经历一些不好的副作用。在Python运行时开始删除主线程中的内容之后,守护线程仍然可以执行,从而导致一些非常奇怪的异常。

更多信息:

https://joeshaw.org/python-daemon-threads-considered-harmful/

https://mail.python.org/pipermail/python-list/2005-February/343697.html

严格地说,你永远不需要它们,它只是在某些情况下使实现更容易。


引用克里斯的话:“……当您的程序退出时,所有守护进程线程将自动被杀死。”我想这就是总结。在使用它们时要小心,因为当主程序执行到完成时,它们会突然终止。


Chris已经解释了守护线程是什么,所以让我们讨论一下实际使用。许多线程池实现使用守护线程作为任务工作者。工作线程是执行任务队列中的任务的线程。

Worker needs to keep waiting for tasks in task queue indefinitely as they don't know when new task will appear. Thread which assigns tasks (say main thread) only knows when tasks are over. Main thread waits on task queue to get empty and then exits. If workers are user threads i.e. non-daemon, program won't terminate. It will keep waiting for these indefinitely running workers, even though workers aren't doing anything useful. Mark workers daemon threads, and main thread will take care of killing them as soon as it's done handling tasks.


当第二个线程不是daemon线程时,应用程序的主主线程不能退出,因为它的退出条件也绑定到非daemon线程的退出。在python中线程不能被强制杀死,因此你的应用程序将不得不等待非daemon线程退出。如果这种行为不是您想要的,那么将第二个线程设置为守护进程,这样它就不会阻止应用程序退出。


我还将在这里补充我的一些内容,我认为daemon线程让大多数人感到困惑的原因之一(至少对我来说是这样)是因为dameon这个词的Unix上下文。

在Unix术语中,daemon一词指的是曾经生成的进程;保持在后台运行,用户可以移动到前台进程做其他事情。

在Python线程上下文中,创建的每个线程都在后台运行,无论是守护进程还是非守护进程,区别在于这些线程如何影响主线程。

当你启动一个非守护线程时,它开始在后台运行,你可以执行其他事情,然而,你的主线程不会退出,直到所有这些非守护线程完成它们的执行,所以在某种程度上,你的程序或主线程被阻塞了。

使用守护线程,它们仍然在后台运行,但有一个关键区别,即它们不会阻塞主线程。 只要主线程完成执行并且程序退出,所有剩余的守护线程将被收割。这使得它们对于那些希望在后台执行但希望这些操作在主应用程序退出时自动退出的操作非常有用。

需要注意的一点是,您应该知道您在守护线程中究竟在做什么,它们在主线程退出时退出的事实可能会给您意想不到的惊喜。优雅地清理守护进程线程的一种方法是使用Threading Events将事件设置为退出处理程序,并检查事件是否在线程内部设置,然后相应地中断线程函数。

关于守护线程的另一件令人困惑的事情是python文档中的定义。

这个标志的意义在于整个Python程序退出 当只剩下守护线程时

简单地说,这意味着如果你的程序同时有守护进程和非守护进程线程,主程序将被阻塞并等待所有非守护进程退出,一旦它们退出主线程也将退出。这句话还暗示(乍一看不清楚),一旦主线程退出,所有守护线程都将自动退出。


创建Daemon线程时:

您需要一个低优先级的线程 你的线程执行特定于后台的任务,更重要的是, 当您希望该线程在所有用户线程完成任务后立即结束时。

Daemon线程服务的一些例子:Java中的垃圾收集,MS Word中的字数检查器,介质中的自动保护程序,并行文件下载应用程序中的文件下载计数器等。