[Python学习日记-92] 并发编程之多线程 —— 守护线程

[Python学习日记-92] 并发编程之多线程 ------ 守护线程

简介

守护线程的概念

守护线程的实现方式

[一、通过 setDaemon() 方法设置](#一、通过 setDaemon() 方法设置)

[二、通过 daemon 参数设置](#二、通过 daemon 参数设置)

[三、继承 Thread 类时设置守护线程](#三、继承 Thread 类时设置守护线程)

主线程等待非守护线程(用户线程)的例子

简介

守护线程(Daemon Thread)是一个不容忽视的概念,它有着独特的运行机制和应用场景,理解并掌握守护线程,能让我们在编写多线程程序时更加得心应手,合理地管理线程资源,优化程序性能。在前面介绍进程时我们也介绍过守护进程,本次要介绍的守护线程与其类似,都是遵循着**"守护线程/进程会等待主线程/进程运行完毕后被销毁"**。接下来,就让我们一同揭开守护线程的神秘面纱。

守护线程的概念

在进程的学习当中也有守护的这一概念,当时我们把其称为守护进程,而守护线程其实和守护进程理念类似,都是子的守护主的,主的结束了子的也一起结束,即子线程的生命周期依赖于主线程,当主线程运行完毕时,无论守护线程是否运行完毕,都会被立即终止。需要强调的是,这里的运行完毕并非指终止运行,对于主进程来说,运行完毕指的是主进程代码运行完毕,进一步来说,**主进程在其代码结束后就已经算运行完毕了,同时守护进程在此时也被回收,然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源才会结束(否则会产生僵尸进程);对于主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程(用户线程)统统运行完毕,**主线程才算运行完毕,此时守护线程就会被回收,总的来说主线程的结束意味着进程的结束,进程整体的资源都将被回收。

守护线程通常用于执行一些辅助性的、后台支持的任务,比如垃圾回收、日志监控、资源清理等。这些任务不需要等待其完全执行完毕就可以结束程序,一旦主线程完成其核心工作,守护线程的使命也就结束了。例如,在一个服务器程序中,可能有一个守护线程负责定期清理过期的缓存数据,当服务器的主线程停止服务时,这个清理缓存的守护线程也应该随之结束,而不需要等待它完成当前的清理任务。

守护线程的实现方式

一、通过 setDaemon() 方法设置

示例代码如下:

python 复制代码
from threading import Thread
import time


def task():
    while True:
        time.sleep(1)
        print("子线程正在执行...")    # 还没执行主线程已经结束了,所以不会打印出来


if __name__ == "__main__":
    t = Thread(target=task)
    t.setDaemon(True)  # 将线程t设置为守护线程,必须在t.start()之前设置
    t.start()
    print("主线程结束")
    print(t.is_alive())

代码输出如下:

在上述代码中,我们定义了一个 task 函数,该函数在一秒后将打印信息。然后创建了一个线程t来执行 task 函数,并通过 setDaemon(True) 将其设置为守护线程。主线程启动子线程后,打印 "主线程结束"。由于子线程是守护线程,当主线程结束时,子线程会立即终止,即使后面的信息还没有打印出来。

注意:setDaemon() 在新版本 Python3 中已经废弃了。

二、通过 daemon 参数设置

示例代码如下:

python 复制代码
from threading import Thread
import time


def task():
    while True:
        time.sleep(1)
        print("子线程正在执行...")    # 还没执行主线程已经结束了,所以不会打印出来


if __name__ == "__main__":
    t = Thread(target=task)
    t.daemon = True  # 将线程t设置为守护线程,必须在t.start()之前设置
    t.start()
    print("主线程结束")
    print(t.is_alive())

代码输出如下:

在上述代码与通过 setDaemon() 方法设置的代码功能一致,所以输出也一致。

三、继承 Thread 类时设置守护线程

示例代码如下:

python 复制代码
from threading import Thread
import time


class MyThread(Thread):
    def __init__(self):
        super().__init__()
        self.daemon = True  # 在初始化方法中设置为守护线程

    def run(self):
        while True:
            print("自定义子线程正在执行...")
            time.sleep(1)


if __name__ == "__main__":
    t = MyThread()
    t.start()
    time.sleep(3)
    print("主线程结束")

代码输出如下:

在这个示例中,我们自定义了 MyThread 类继承自 Thread 类,并在 init 方法中设置 self.daemon = True,将自定义线程设置为守护线程。在 run 方法中每隔一秒无限循环的输出指定信息,主线程启动子线程后休眠 3 秒结束,此时守护线程也会随之终止。

主线程等待非守护线程(用户线程)的例子

示例代码如下:

python 复制代码
from threading import Thread
import time

def foo():
    print('foo子线程开始了...')
    time.sleep(1)
    print('foo子线程结束了...')

def bar():
    print('bar子线程开始了...')
    time.sleep(3)
    print('bar子线程结束了...')

if __name__ == '__main__':
    t1 = Thread(target=foo)
    t2 = Thread(target=bar)

    t1.daemon = True
    t1.start()
    t2.start()
    print('主线程所在进程的代码执行完了...')

代码输出如下:

相关推荐
你好~每一天8 分钟前
2025年B端产品经理进阶指南:掌握这些计算机专业技能,决胜职场!
java·人工智能·经验分享·学习·产品经理·大学生
努力打怪升级12 分钟前
容器学习day05_k8s(二)
学习·容器·kubernetes
MonkeyKing_sunyuhua12 分钟前
mac怎么安装uv工具
python·macos·uv
叫我Zoe就行19 分钟前
MySQL集群——主从复制
linux·数据库·学习·mysql
Source.Liu23 分钟前
【Python基础】 19 Rust 与 Python if 语句对比笔记
笔记·python·rust
程序喵大人40 分钟前
写C++十年,我现在怎么设计类和模块?(附真实项目结构)
开发语言·c++·类和模板
维斯路42 分钟前
ANSYS 热力耦合计算
学习
工业互联网专业1 小时前
基于Spark的新冠肺炎疫情实时监控系统_django+spider
python·spark·django·vue·毕业设计·源码·课程设计
Yh8702031 小时前
2025年经济学专业女生必考证书指南:打造差异化竞争力
python
黄焖鸡能干四碗1 小时前
信息系统安全保护措施文件方案
大数据·开发语言·人工智能·web安全·制造