Python 中的守护线程 – 它们是什么以及如何创建它们?

大家好!在今天的文章中,我们将讨论如何在 Python 中使用守护线程。在开始正题之前,我们先来看看什么是守护线程!


守护线程

守护线程是一种可以在后台独立运行的线程。这些类型的线程独立于主线程执行。所以这些被称为非阻塞线程。

什么时候你可能需要 Python 中的守护线程?

假设您需要一个长时间运行的任务来尝试读取日志文件。当此任务在日志中检测到错误消息时,必须提醒用户。

我们可以为此任务分配一个守护线程,它可以继续监视我们的日志文件,而我们的主程序则执行通常的工作!

守护线程最好的部分是,一旦主程序完成,它们就会自动停止执行!

如果您需要一个短任务,守护线程将在返回后停止执行。然而,由于这种性质,守护线程广泛用于长时间运行的后台任务。

现在,让我们看一个示例,展示如何在 Python 中使用它们!


在 Python 中使用守护线程 – 实践实现

Python 中的这些示例将使用Python 中的线程模块,该模块是标准库的一部分。

import threading

为了说明守护线程的强大功能,我们首先创建两个线程 A 和 B。

我们将使线程 A执行简短的计算,而线程 B尝试监视共享资源。

如果此资源设置为True,我们将使线程 B 向用户发出有关状态的警报。

import threading
import time
 
# Set the resource to False initially
shared_resource = False
 # A lock for the shared resource
lock = threading.Lock()
 
def perform_computation():
     
    # Thread A will call this function and manipulate the resource
    print(f'Thread {threading.currentThread().name} - performing some computation....')
    shared_resource = True
    print(f'Thread {threading.currentThread().name} - set shared_resource to True!')
    print(f'Thread {threading.currentThread().name} - Finished!')
    time.sleep(1)
 
def monitor_resource():
    # Thread B will monitor the shared resource
    while shared_resource == False:
        time.sleep(1)
    print(f'Thread {threading.currentThread().name} - Detected shared_resource = False')
    time.sleep(1)
    print(f'Thread {threading.currentThread().name} - Finished!')
 
 
if __name__ == '__main__':
    a = threading.Thread(target=perform_computation, name='A')
    b = threading.Thread(target=monitor_resource, name='B')
 
    # Now start both threads
    a.start()
    b.start()

这里,线程A将设置shared_resourceTrue线程B将等待该资源为True。

输出

Thread A - performing some computation....
Thread A - set shared_resource to True!
Thread A - Finished!
Thread B - Detected shared_resource = False
Thread B - Finished!

请注意,两个线程都是普通线程。现在让我们将线程 B 设为守护线程。让我们看看现在会发生什么。

为此,我们可以将其设置为threading.Thread(daemon=True)方法中的参数。

import threading
import time
 
shared_resource = False # Set the resource to False initially
lock = threading.Lock() # A lock for the shared resource
 
def perform_computation():
    # Thread A will call this function and manipulate the resource
    print(f'Thread {threading.currentThread().name} - performing some computation....')
    shared_resource = True
    print(f'Thread {threading.currentThread().name} - set shared_resource to True!')
    print(f'Thread {threading.currentThread().name} - Finished!')
    time.sleep(1)
 
def monitor_resource():
    # Thread B will monitor the shared resource
    while shared_resource == False:
        time.sleep(1)
    print(f'Daemon Thread {threading.currentThread().name} - Detected shared_resource = False')
    time.sleep(1)
    print(f'Daemon Thread {threading.currentThread().name} - Finished!')
 
 
if __name__ == '__main__':
    a = threading.Thread(target=perform_computation, name='A')
    b = threading.Thread(target=monitor_resource, name='B', daemon=True) # Make thread B as a daemon thread
 
    # Now start both threads
    a.start()
    b.start()

输出

Thread A - performing some computation....
Thread A - set shared_resource to True!
Thread A - Finished!
Daemon Thread B - Detected shared_resource = False

在这里,请注意守护线程尚未完成。这是因为它会自动被主线程杀死。

守护线程的非阻塞特性使其对于许多 Python 应用程序非常有用。


结论

在本文中,我们了解了如何在 Python 应用程序中使用守护线程


参考

  • Python 线程模块文档
  • JournalDev 关于 Python 中守护线程的文章