python线程(python threading模块、python多线程)(守护线程与非守护线程)

文章目录

    • Python多线程入门
      • 1. Python多线程概述
      • 2. `threading`模块基础
        • - Thread 类: 这是一个代表线程的类。可以通过创建`Thread`类的实例来新建一个线程。
        • - Lock 类: 在多线程环境中,为了防止数据错乱,通常需要用到锁机制。`Lock`类提供了基本的锁功能,可以帮助同步线程。
        • - Condition 类: 这是一种更高级的线程同步机制,它在某些条件下阻塞线程,直到被其他线程唤醒。
      • 3. 创建线程
      • 4. 线程间通信
      • 5. 线程同步
    • Python Threading模块各类详解
      • Thread 类
        • - target:指定线程启动时要执行的函数。
        • - args:是一个元组,表示传递给目标函数的参数。
        • - kwargs:是一个字典,表示传递给目标函数的关键字参数。
        • - name:为线程指定一个名称,这在调试时很有用。
        • - daemon:布尔值,指示线程是否是守护线程(守护线程会随着主线程的退出而退出)。
          • 参数
          • 守护线程的特性
          • 示例(守护线程与非守护线程)
            • - 守护线程(主程序退出守护线程将会被强制退出):
            • - 非守护进程(主程序退出,非守护线程照样执行,直到它自己运行完)
        • 示例:
      • Lock 类
        • - acquire(blocking=True, timeout=-1):尝试获得锁。`blocking`参数为`False`时,方法会立即返回一个布尔值,表示是否获取到了锁。`timeout`指定等待锁的最长时间。
        • - release():释放锁。
        • 示例:
      • Semaphore 类
        • - acquire(blocking=True, timeout=-1):同`Lock`的`acquire`。
        • - release():释放信号量。
        • 示例:
      • Event 类
        • - set():将事件状态设置为真。
        • - clear():将事件状态设置为假。
        • - wait(timeout=None):阻塞线程,直到事件的状态为真或超时。
        • 示例:
      • Condition 类
        • - acquire() / release():与Lock相同,用于获取和释放底层锁。
        • - wait(timeout=None):调用线程等待,直到被notify()或notify_all()唤醒或超时。
        • - notify(n=1):唤醒一个或多个正在等待这个条件的线程。`n` 指定要唤醒的线程数。
        • - notify_all():唤醒所有等待这个条件的线程。
        • 示例:
      • Barrier 类
        • - parties:这是Barrier类构造函数的主要参数,代表需要到达屏障点的线程数。只有当指定数量的线程都已调用了wait()方法,所有这些线程才会同时被释放继续执行。这个数字必须在创建Barrier时确定,并在其生命周期内保持不变。
        • - wait():阻塞调用此方法的线程,直到所有线程都已调用此方法。然后所有线程同时释放。
        • 示例:
      • Timer 类
        • - interval:定时器激活之前的延迟时间(秒)。
        • - function:定时器激活时要执行的函数。
        • - args / kwargs:传递给 function 的参数。
        • 示例:
      • 参考文章

Python多线程入门

1. Python多线程概述

Python多线程是一种允许程序同时执行多个任务的技术。它主要通过threading模块实现,该模块提供了丰富的API来创建和管理线程。使用多线程可以提高程序的执行效率,尤其是在执行多个独立的任务时,或者在进行大量的I/O操作时。

2. threading模块基础

threading模块是Python中用于实现多线程的标准库之一。这个模块中包含了多个类和函数,可以帮助开发者创建和管理线程。

- Thread 类: 这是一个代表线程的类。可以通过创建Thread类的实例来新建一个线程。
- Lock 类: 在多线程环境中,为了防止数据错乱,通常需要用到锁机制。Lock类提供了基本的锁功能,可以帮助同步线程。
- Condition 类: 这是一种更高级的线程同步机制,它在某些条件下阻塞线程,直到被其他线程唤醒。

3. 创建线程

创建线程的基本方法是实例化Thread类,它接受一个目标函数和函数的参数。下面是一个简单的示例:

import threadingdef print_numbers(n):for i in range(1, n + 1):print(i)# 创建线程
thread = threading.Thread(target=print_numbers, args=(10,))
# 启动线程
thread.start()
# 等待线程完成
thread.join()

在这里插入图片描述

这段代码定义了一个打印数字的函数,并在一个新线程中运行这个函数。

4. 线程间通信

线程间的通信可以通过全局变量、队列等方式实现。Python的queue.Queue类是线程安全的,非常适合用来进行线程间的数据传递。

import threading
import queue# 创建一个队列
q = queue.Queue()def producer():for i in range(10):q.put(i)print(f"Produced {i}")def consumer():while True:item = q.get()if item is None:breakprint(f"Consumed {item}")q.task_done()# 创建生产者和消费者线程
t1 = threading.Thread(target=producer)
t2 = threading.Thread(target=consumer)t1.start()
t2.start()t1.join()
q.put(None)  # 用None来通知消费者结束
t2.join()

在这里插入图片描述

5. 线程同步

在多线程环境中,线程同步是非常重要的。这可以通过锁(Lock)来实现。下面的示例展示了如何使用锁来确保多个线程可以安全地修改共享数据。

import threading# 共享资源
counter = 0
lock = threading.Lock()def update_counter():global counterwith lock:current = countercurrent += 1counter = currentprint(f"Counter: {counter}")threads = []
for i in range(10):t = threading.Thread(target=update_counter)t.start()threads.append(t)for t in threads:t.join()

在这里插入图片描述

注意:t.join() 是一个阻塞调用。当在一个线程中调用 join() 方法时,它会阻塞调用它的线程(通常是主线程),直到被 join() 的线程(即 t)执行完毕。这意味着主线程将等待 t 线程结束其执行,然后才继续执行 join() 之后的代码。

join() 方法通常用于确保线程在程序继续执行之前完成其任务,特别是当主线程需要从其他线程中获得结果或确保所有子线程在继续之前完成时。这是一种同步技术,用于协调不同线程间的执行顺序。

这段代码创建了10个线程,每个线程都尝试更新全局变量counter。通过锁lock,确保了每次只有一个线程可以修改counter


确实,之前的回答中只是简要介绍了threading模块的一些基础用法。下面将详细介绍threading模块中几个重要的类和函数,以及它们的参数和用法:

Python Threading模块各类详解

Thread 类

Thread类是threading模块中用来创建和管理线程的主要类。主要参数如下:

- target:指定线程启动时要执行的函数。
- args:是一个元组,表示传递给目标函数的参数。
- kwargs:是一个字典,表示传递给目标函数的关键字参数。
- name:为线程指定一个名称,这在调试时很有用。
- daemon:布尔值,指示线程是否是守护线程(守护线程会随着主线程的退出而退出)。
参数

在 Python 的 threading 模块中,daemon 属性是用来指定线程是否为守护线程(daemon thread)。这个属性接受一个布尔值,用来定义线程的行为:

  • True:线程被设置为守护线程。守护线程在程序退出时不会阻止程序的终止。也就是说,当主程序结束时,所有的守护线程将被强制终止,无论是否运行完成。
  • False:线程被设置为非守护线程(默认值)。非守护线程必须在程序退出前完成或被显式地结束,否则程序会等待这些线程结束后才能完全退出。
守护线程的特性

守护线程通常用于在后台运行的服务或任务,如日志写入、系统监控等。这些任务通常是周期性的,不需要和程序主逻辑同步结束。设置线程为守护线程可以防止这些后台任务延长主程序的生命周期。

示例(守护线程与非守护线程)

下面的代码示例演示了如何设置守护线程,并观察守护线程与非守护线程的行为差异:

- 守护线程(主程序退出守护线程将会被强制退出):
import threading
import timedef daemon_thread():while True:time.sleep(1)print("Daemon thread is running...")# 创建守护线程
daemon = threading.Thread(target=daemon_thread)
daemon.daemon = True# 启动线程
daemon.start()print("Main program exits.")

在这里插入图片描述

- 非守护进程(主程序退出,非守护线程照样执行,直到它自己运行完)
import threading
import timedef non_daemon_thread():for i in range(5):time.sleep(1)print("Non-daemon thread is running...")# 创建非守护线程
non_daemon = threading.Thread(target=non_daemon_thread)# 启动线程
non_daemon.start()print("Main program exits.")

在这里插入图片描述

示例:
import threadingdef worker(num):"""线程执行的目标函数"""print(f"Worker: {num}")threads = []
for i in range(5):t = threading.Thread(target=worker, args=(i,), name=f"thread-{i}")t.start()threads.append(t)for t in threads:t.join()

在这里插入图片描述

Lock 类

Lock类用于线程同步,主要方法有:

- acquire(blocking=True, timeout=-1):尝试获得锁。blocking参数为False时,方法会立即返回一个布尔值,表示是否获取到了锁。timeout指定等待锁的最长时间。
- release():释放锁。
示例:
import threadinglock = threading.Lock()def worker(num):lock.acquire()try:print(f"Worker: {num}")finally:lock.release()threads = []
for i in range(5):t = threading.Thread(target=worker, args=(i,))t.start()threads.append(t)for t in threads:t.join()

在这里插入图片描述

Semaphore 类

信号量是一种更高级的同步机制,允许多个线程同时访问相同的资源,但有限制的数量。

- acquire(blocking=True, timeout=-1):同Lockacquire
- release():释放信号量。
示例:
import threadingsemaphore = threading.Semaphore(2)def worker(num):with semaphore:print(f"Worker: {num}")threads = []
for i in range(5):t = threading.Thread(target=worker, args=(i,))t.start()threads.append(t)for t in threads:t.join()

在这里插入图片描述

Event 类

事件是一个简单的同步机制,主要用于线程间的事件通知。

- set():将事件状态设置为真。
- clear():将事件状态设置为假。
- wait(timeout=None):阻塞线程,直到事件的状态为真或超时。
示例:
import threadingevent = threading.Event()def waiter(event, n):print(f"Thread {n} waiting for event")event.wait()print(f"Thread {n} proceeding")def setter(event):print("Setting event")event.set()t1 = threading.Thread(target=waiter, args=(event, 1))
t2 = threading.Thread(target=waiter, args=(event, 2))
t3 = threading.Thread(target=setter, args=(event,))t1.start()
t2.start()
t3.start()t1.join()
t2.join()
t3.join()

在这里插入图片描述

当然,threading 模块除了包括 Thread, Lock, Semaphore, 和 Event 类外,还有其他一些有用的同步原语和工具,可以帮助解决线程之间的协调和状态共享问题。下面介绍几个其他常用的类:

Condition 类

Condition类用于复杂的线程同步问题。本质上,它是一个围绕锁(Lock)的更高级的锁,允许一个线程等待某个条件,而让其他线程发出条件已满足的信号。

- acquire() / release():与Lock相同,用于获取和释放底层锁。
- wait(timeout=None):调用线程等待,直到被notify()或notify_all()唤醒或超时。
- notify(n=1):唤醒一个或多个正在等待这个条件的线程。n 指定要唤醒的线程数。
- notify_all():唤醒所有等待这个条件的线程。
示例:
import threadingcondition = threading.Condition()def consumer(cond):with cond:print("Consumer waiting")cond.wait()print("Consumer proceed")def producer(cond):with cond:print("Producer ready, notifying consumer")cond.notify_all()t1 = threading.Thread(target=consumer, args=(condition,))
t2 = threading.Thread(target=producer, args=(condition,))t1.start()
t2.start()t1.join()
t2.join()

在这里插入图片描述

Barrier 类

Barrier类用于创建一个同步点,线程必须同时到达这个点才能继续执行。这在某些并行算法中非常有用,需要所有并行任务同时到达某个计算阶段后才能继续。

- parties:这是Barrier类构造函数的主要参数,代表需要到达屏障点的线程数。只有当指定数量的线程都已调用了wait()方法,所有这些线程才会同时被释放继续执行。这个数字必须在创建Barrier时确定,并在其生命周期内保持不变。
- wait():阻塞调用此方法的线程,直到所有线程都已调用此方法。然后所有线程同时释放。
示例:
import threadingbarrier = threading.Barrier(2)def worker(barrier, num):print(f"Worker {num} reaching barrier")barrier.wait()print(f"Worker {num} passed barrier")t1 = threading.Thread(target=worker, args=(barrier, 1))
t2 = threading.Thread(target=worker, args=(barrier, 2))t1.start()
t2.start()t1.join()
t2.join()

在这里插入图片描述

Timer 类

TimerThread 的子类,用于在指定的时间后启动一个操作。

- interval:定时器激活之前的延迟时间(秒)。
- function:定时器激活时要执行的函数。
- args / kwargs:传递给 function 的参数。
示例:
import threadingdef delayed_function():print("Timer activated")timer = threading.Timer(5.0, delayed_function)
timer.start()  # 5秒后,打印输出

在这里插入图片描述

这些类提供了不同的同步机制,使得多线程程序可以更加精细地控制线程间的交互和协调。在设计多线程应用时,了解和选择合适的同步机制是非常重要的,可以帮助避免死锁和竞争条件等问题。


这些类和方法为Python中的多线程编程提供了丰富的支持,使得可以在多种场景下有效地使用线程。


以上内容是对Python多线程的一个基础介绍,涵盖了创建线程、线程间通信和线程同步的基本概念和方法。在实际应用中,根据具体需求选择合适的同步机制和通信方式是非常重要的。

参考文章

参考文章:python线程创建和传参(33)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145729.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如日中天的AI大模型,也到了发展幻灭期!

近期 Gartner发布了《新兴技术成熟度曲线》,其中生成式 AI (GenAI) 正式进入到了幻灭期。 2018 年 6 月,OpenAI发布GPT-1模型,生成式AI开始向产品化发展。 到2022年的GPT-3.5发布,并且ChatGPT首次向公众推…

企业微信-前往服务商后台页面对接解决方案

序 我会告诉你在哪里点我会告诉你在哪里配置点下去他只返回auth_code的,我怎么登录 正文 他是在这个位置 是这样,应用授权安装第三方应用后,企业微信(管理员角色)是可以从pc端企业后台点第三方应用的。 如果我没记…

【qt】一个WPS项目了解qt界面设计的基本套路

项目功能演示: 放心食用!最后有完整代码. 超级详细,期待您的一个点赞❥(^_-) 一览全局: WPS项目目录 一.创建项目二.导入资源三.ui设计四.字号选择框初始化五.滚动条初始化六.添加自定义文本类七.初始化action状态八.新建文档九.打开文件十.保存与另存为十一.打印/打印预览十…

QT设置git仓库

笔者最近想写一个qt的程序,想要把这个代码推送到github上。 前提是电脑已安装了git、QT 以下是设置步骤: 1.设置QT中关于git的配置 打开QT,点击工具-》选项-》版本控制-》填写PATH 这个PATH是你安装git的绝对路径,如果你不记得…

HTTP中的Cookie与Session

一、背景 HTTP协议是无状态无连接的。 无状态:服务器不会保存客户端历史请求记录,每一次请求都是全新的。 无连接:服务器应答后关闭连接,每次请求都是独立的。 无状态就导致服务器不认识每一个请求的客户端是否登陆过。 这时…

Mybatis框架映射---代码实现(XML配置以及注解形式)

目录 一. 映射关系 1 对 1-映射方式 1.通过xml文件实现映射的一对一关系 总结 : 2.通过注解的方式来实现下面的 1 对 1 的映射关系,实现级联查询 总结: 二. 映射关系多对一 1.通过xml文件实现映射的多对一关系 2.通过注解的方式来实现…

【Elasticsearch系列十五】强大特性

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

MapReduce基本原理

目录 整体执行流程​ Map端执行流程 Reduce端执行流程 Shuffle执行流程 整体执行流程 八部曲 读取数据--> 定义map --> 分区 --> 排序 --> 规约 --> 分组 --> 定义reduce --> 输出数据 首先将文件进行切片(block)处理&#xff…

EsDA,一站式嵌入式软件

EsDA是一套面向工业智能物联领域的嵌入式系统设计自动化工具集,包含实时操作系统AWorksLP、低代码开发平台AWStudio、资源管理平台AXPI、跨平台GUI引擎AWTK和云服务平台ZWS,旨在提高嵌入式软件开发的效率、性能和可扩展性。 EsDA全称是嵌入式系统设计自动…

司南 OpenCompass 九月大语言模型评测榜单启动召集,欢迎新合作厂商申请评测

主要概览 司南 OpenCompass 大语言模型官方自建榜单(9 月榜)评测拟定于 10 月上旬发布,现诚挚邀请新加入的合作方参与评测。本次评测围绕强化能力维度,全面覆盖语言、推理、知识、代码、数学、指令跟随、智能体等七大关键领域&am…

ThreaLocal

1.概述 ThreadLoca称线程局部变量,用于在线程中保存数据,保存的数据仅属于当前线程(即对其他线程而言,该变量是当前线程独有的变量) threadLocal利用Thread中的ThreadLocalMap来进行数据存储 2.常用方法 存储数据至当前线程ThreadLocalMap中…

Unity引擎绘制多边形属性图

大家好,我是阿赵   在制作游戏的时候,经常会遇到需要绘制多边形属性图的需求,比如这种效果: 可以根据需要的属性的数量变化多边形的边数,然后每一个顶点从中心点开始到多边形的顶点的长度代表了该属性的强度&#xf…

谈对象第二弹: C++类和对象(中)

文章目录 一、类的默认成员函数二、构造函数三、析构函数四、拷贝构造函数五、运算符重载5.1运算符重载5.2赋值运算符重载5.3实现日期类<<、>>重载检查、获取天数关系运算符重载算数、赋值运算符重载Date.hDate.cpp 六、取地址运算符重载6.1const成员函数6.2取地址…

docker部署excalidraw画图工具

0&#xff09;效果 0.1&#xff09;实时协作 0.2&#xff09;导出格式 1&#xff09;docker安装 docker脚本 bash <(curl -sSL https://cdn.jsdelivr.net/gh/SuperManito/LinuxMirrorsmain/DockerInstallation.sh)docker-compose脚本 curl -L "https://github.com/…

Dynaform 5.9.4简体中文版百度云下载(含教程)

如大家所了解的&#xff0c;Dynaform是一种基于有限元分析&#xff08;FEA&#xff09;技术的计算机辅助工程&#xff08;CAE&#xff09;软件&#xff0c;常常用于模拟和优化各种工业应用中的结构和流体问题。 目前常用的版本为Dynaform 5.9.4&#xff0c;可以模拟机械结构、…

第314题|参考!如何做到【一题多解】|武忠祥老师每日一题

解析&#xff1a; 画出图像&#xff1a; 观察选项可知&#xff1a;选项A和选项B是相反选项&#xff0c;因此答案只能在AB当中。 因此本题我们只需要算出和的大小即可。 方法一&#xff1a;直接相减然后判断结果的正负。 分析题目给的条件&#xff1a;f(x)单调减少&#xff0…

肥胖成因:饮食之外,消耗吸收慢是关键因素

肥胖问题一直被现代社会所关注&#xff0c;不可否认&#xff0c;饮食是影响胖瘦的重要因素之一。高热量、高油脂的食物摄入过多&#xff0c;也确实会导致热量油脂过剩&#xff0c;堆积储存进身体内进而养肥身体。可在正常情况中&#xff0c;就算是消耗吸收率一般的人&#xff0…

828华为云征文 | 在Huawei Cloud EulerOS系统中安装Docker的详细步骤与常见问题解决

前言 Docker是一种轻量级的容器技术&#xff0c;广泛用于应用程序的开发、部署和运维。在华为云的欧拉&#xff08;Huawei Cloud EulerOS&#xff09;系统上安装和运行Docker&#xff0c;虽然与CentOS有相似之处&#xff0c;但在具体实现过程中&#xff0c;可能会遇到一些系统…

进程状态的优先级

1.进程的状态&#xff08;所有系统&#xff09; 因为是对于所有系统的&#xff0c;所以描述会很抽象。 补充知识&#xff1a; 并行和并发 并行&#xff1a;多个进程再多个cpu下分别同时运行并发&#xff1a;多个进程在一个cpu下采取进程切换的方式&#xff0c;在一段时间内&…

echarts实现地图下钻并解决海南群岛显示缩略图

一、准备工作 1、echarts版本&#xff1a; ^5.5.1 2、去掉海南数据的json文件 二、获取删除过后的json文件 1、DataV.GeoAtlas地理小工具系列 (aliyun.com) 在网站输入这个复制的&#xff0c;新建一个json文件粘贴进去。 接下来需要删除两个地方&#xff0c;不要删错&…