当前位置: 首页 > news >正文

Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程

若事与愿违,请相信,上天自有安排,允许一切如其所是

                                                                                —— 24.11.12

一、进程、线程

现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。

进程

进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理。线程就是程序在系统中运行起来,被系统所管理的一个逻辑概念

进程就好比一家公司,是操作系统对程序进行运行管理的单位


线程

线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程实际工作的最小单位。

线程就好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者

操作系统中可以运行多个进程,即多任务运行

一个进程内可以运行多个线程,即多线程运行


注意点:

进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所。

线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。这就好比,公司员工之间是共享公司的办公场所。 


二、并行执行

并行执行的意思指的是同一时间做不同的工作

进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行

除了进程外,线程其实也是可以并行执行的,也就是比如一个Python程序,其实是完全可以做到

        一个线程在输出:你好

        一个线程在输出:Hello

像这样一个程序在同一时间做两件乃至多件不同的事情,我们就称之为:多线程并行执行


三、threading模块

绝大多数编程语言,都允许多线程编程,Pyhton也不例外。

Python的多线程可以通过threading模块来实现。

语法

thread_obj = threading.Thread([group [, target [, name [, args [,  kwargs]]]]])

— self:在实例化对象并调用方法时会自动传入对象本身的引用。在这里表示当前正在被初始化的线程对象实例

— group:暂时无用,未来功能的预留参数

— target:执行的目标任务名

— name:线程名,一般不用设置

— args:以元组的方式给执行任务传参

— kwargs:以字典方式给执行任务传参

— daemon:用于设置线程是否为守护线程

守护线程是一种在后台运行的线程,当主线程结束时,守护线程通常也会随之结束(即使它自己的任务可能还没有完成)


示例

'''
演示多线程的使用
'''
import time
import threadingdef sing():while True:print("唱歌ing")time.sleep(1)def dance():while True:print("跳舞ing")time.sleep(1)if __name__ == '__main__':sing_thread = threading.Thread(target=sing)dance_thread = threading.Thread(target=dance)# 启动线程sing_thread.start()dance_thread.start()


需要传参的话可以通过:

① args参数通过元组(按参数顺序)的方式传参

② 或使用kwargs参数用字典的形式传参

'''
演示多线程的使用
'''
import time
import threadingdef sing(msg):while True:print(msg)time.sleep(1)def dance(msg):while True:print(msg)time.sleep(1)if __name__ == '__main__':# 以元组方式传参sing_thread = threading.Thread(target=sing,args=("我要唱歌",))# 以字典方式传参dance_thread = threading.Thread(target=dance,kwargs={"msg": "我要跳舞"})# 启动线程sing_thread.start()dance_thread.start()


四、多线程编程

1.threading模块的使用

thread_obj = threading.Thread(target=func)        创建线程对象
thread obj.start()        启动线程执行

2.如何传参

① 元组方式

    # 以元组方式传参sing_thread = threading.Thread(target=sing,args=("我要唱

② 字典方式

    # 以字典方式传参dance_thread = threading.Thread(target=dance,kwargs={"msg": "我要跳舞"}

3.线程类 threading

current_thread()    返回与Thread调用方的控制线程相对应的当前对象。
enumerate()            返回Thread当前所有活动对象的列表。
active_count()    返回Thread当前活动的对象数。返回的计数等于所返回列表的长度enumerate()。
main_thread()     返回主要Thread对象。在正常情况下,主线程是启动Python解释器的线程。
get_ident()      返回当前线程的“线程标识符”。这是一个非零整数。它的值没有直接的意义。


4.线程对象 threading.Thread()

守护线程

主线程不管守护线程的执行情况,只要是其他子线程结束且主线程执行完毕,主线程部会关闭。

常见方法

1、setDaemon(True)        可以把子线程设置为主线程的守护线程,此方法必须在start之前

2、join()        让主线程等待子线程执行,此方法在start之后

示例

"""
守护线程:
主线程不管守护线程的执行情况,只要是其他子线程结束且主线程执行完毕,主线程都会关闭。
常见方法:
1、setDaemon(True)方法可以把子线程设置为主线程的守护线程,此方法必须在start之前
2、join()方法,让主线程等待子线程执行,此方法在start之后
"""import threading
import timedef run1(name, n):for _ in range(n):  # _下划线表示临时变量, 仅用一次,后面无需再用到print(name, time.ctime())time.sleep(1)def run2(name, n):for _ in range(n):print(name, time.ctime())time.sleep(1)if __name__ == '__main__':"""设置子线程t1为守护线程,主线程不等t1运行结束,只要其他的子线程t2运行结果,就会关闭主线程。"""t1 = threading.Thread(target=run1, args=("线程1", 10,))  # 注意args参数类型是元组并以“,”结尾t2 = threading.Thread(target=run2, args=("线程2", 5,))t1.setDaemon(True)  # 设置t1为守护线程t1.start()t2.start()

5.线程锁对象

acquire()        锁定        一旦线程获取了锁,随后的尝试将其阻塞,直到释放为止。任何线程都可以释放它。
release()        解锁

互斥锁 threading Lock

递归锁 threading RLock


6.条件对象 threading Condition

threading.condition 是 Python 标准库中用于线程间同步的一个高级机制。它将锁(Lock 或RLock )和条件变量组合在一起,使得线程可以在满足特定条件时等待,并且在条件满足时被唤醒。本质上,它提供了一种更灵活的线程间通信方式,基于共享资源的某种状态(条件)来控制线程的执行。

可以把Condiftion理解为一把高级的锁,它提供了比Lock,RLock更高级的功能,允许我们能够控制复杂的线程同步问题。

主要方法

① acquire 和 release 方法:

acquire 方法用于获取关联的锁。这和单独使用锁的操作类似,当一个线程调用 acquire 时,它会尝试获取锁。如果锁已经被其他线程持有,那么这个线程会被阻塞,直到锁被释放。

release 方法用于释放关联的锁,在完成对共享资源的操作后,线程应该释放锁,以便其他线程可以获取锁并访问共享资源。例如:

import threading
cond = threading.Condition()
cond.acquire()
try:# 在这里访问共享资源
finally:cond.release()
②  wait方法:

线程调用 wait 方法时,会释放当前持有的锁,并进入等待状态。这个线程会一直等待,直到被其他线程通过 notify 或 notify_all 方法唤醒。被唤醒后,线程会重新尝试获取锁,只有获取到锁后才能继续执行后续代码。

import threading
buffer = []
cond = threading.Condition()
def consumer():with cond:while not buffer:print("消费者:缓冲区为空,等待数据...")cond.wait()data = buffer.pop(0)print("消费者:消费了数据", data)
③ notify 和 notify_all 方法:

notify方法用于唤醒一个正在等待该条件变量的线程。在共享资源的状态发生改变,可能使得等待的线程能够继续执行时,应该调用这个方法来唤醒一个等待的线程。

notify_all方法则会唤醒所有正在等待该条件变量的线程。不过,只有在这些被唤醒的线程成功获取到锁后,才能真正继续执行。例如,生产者生产了新的数据后,可以调用 notify 方法唤醒等待的消费者线程:

import threading
buffer = []
cond = threading.Condition()
def producer():with cond:data = 1  # 假设生产的数据为1buffer.append(data)print("生产者:生产了数据", data)cond.notify()

7.信号量对象 threading Semaphole

Semaphore()        内部计数器

BoundedSemaphore()        继承Semaphore类,设定信号量边界值

"""
信号量(BoundedSemaphore类):
信号量通常用于保护容量有限的资源
信号量管理一个内部计数器,该内部计数器随每个acquire()调用而递减,并随每个 调用而递增release()。
计数器永远不能低于零。当acquire() 发现它为零时,它将阻塞,直到其他线程调用为止 release()。
"""import threading, time# 设置信号量的边界值
semaphore = threading.BoundedSemaphore(value=3)def run():semaphore.acquire()  # 加锁print(threading.current_thread().getName(), time.ctime())time.sleep(5)semaphore.release()  # 释放if __name__ == '__main__':for _ in range(10):t = threading.Thread(target=run)t.start()# 返回Thread当前所有活动对象的列表。通过运行结果我们可以看出系统是先一次性创建10个线程,然后根据信号量边界值3,一次性运行3个线程,其他线程等待锁。print(threading.enumerate())"""
python多线程的缺陷:
1、GIL-全局解释器锁
2、无论系统CPU是几核的,只能使用一个来处理进程
"""

 


8.事件对象 threading Event

set()                  将事件对象的内部标志设置为 True 。这意味着等待这个事件的线程将会被唤醒并继续执行

import threading
event = threading.Event()
# 其他线程在等待这个事件
event.set()

clear()                  将事件对象的内部标志设置为 False 。如果在 clear 之后有线程调用 wait 方法,这些线程将会被阻塞,直到事件再次被设置。例如:

import threading
event = threading.Event()
event.set()
# 现在清除事件
event.clear()

wait(timeout=None)               如果“Flag"值为 False,那么当程序执行event.wait方法时就会阻塞;如果“Flag"值为True,那么执行event.wait方法时便不再阻塞

import threading
event = threading.Event()
def worker():print("线程开始等待事件")event.wait()print("事件已触发,线程继续执行")
t = threading.Thread(target=worker)
t.start()
# 在这里可以进行一些其他操作,然后设置事件
event.set()

is set()                 这是一个只读属性,用于检查事件对象的内部标志是否为 true 。可以用于在不阻塞线程的情况下检查事件的状态。例如:

import threading
event = threading.Event()
if not event.is_set():print("事件尚未设置")
event.set()
if event.is_set():print("事件已设置")
"""
事件对象 threading.Event
set()	将“Flag”设置为True
clear()	将“Flag”设置为False
wait()	如果“Flag”值为 False,主线程就会阻塞;如果“Flag”值为True,主线程不再阻塞。
isSet() 判断“Flag”值是否为True。
"""
import threading
import time#实例化一个事件对象
event = threading.Event()def run():while not event.isSet():print(threading.current_thread().getName(), time.ctime())time.sleep(5)event.wait(timeout=10)  # 阻塞线程,为什么timeout=10没起到作用if __name__ == '__main__':#使用多线程去调用runfor i in range(10):th = threading.Thread(target=run)th.start()#阻塞30s后运行主线程time.sleep(30)event.set()


9.Timer计时器对象 threading Timer

参数:(self, interval, function, args=None, kwargs=None)

start()        启动计时器

cancel()        停止计时器(在其动作开始之前)

"""
Timer对象
"""
import threading# 实例化一个计时器
timer = threading.Timerdef hello():print("hello, world")# 10s后执行hello
print("开始执行")
t = timer(10, hello)
t.cancel()
t.start()

相关文章:

Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程

若事与愿违,请相信,上天自有安排,允许一切如其所是 —— 24.11.12 一、进程、线程 现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。 进程 进程:就…...

nuget 管理全局包、缓存和临时文件夹

查看文件夹位置 dotnet nuget locals all --list清空数据 # Clear the 3.x cache (use either command) dotnet nuget locals http-cache --clear nuget locals http-cache -clear# Clear the 2.x cache (NuGet CLI 3.5 and earlier only) nuget locals packages-cache -clea…...

linux物理内存管理:node,zone,page

一、总览 对于物理内存内存,linux对内存的组织逻辑从上到下依次是:node,zone,page,这些page是根据buddy分配算法组织的,看下面两张图: 上面的概念做下简单的介绍: Node&#xff1a…...

uniapp 设置安全区域

<!-- 获取安全区域 --> <script setup lang"ts"> import { computed, ref } from vuelet systemType ref(1) // #ifdef APP-PLUS || H5 || APP-PLUS-NVUE systemType.value 1 const { safeAreaInsets } uni.getSystemInfoSync() console.log(safeAre…...

渐进式JavaScript框架Vue 3 入门

目录 前言1. Vue 3 的基础入门1.1 什么是 Vue.js1.2 局部使用 Vue 2. Vue 3 的基本配置2.1 准备 HTML 页面并引入 Vue 模块2.2 创建 Vue 应用实例 3. Vue 的数据绑定与界面渲染3.1 插值表达式 4. 常用指令详解4.1 v-for 指令&#xff1a;列表渲染4.2 v-bind 指令&#xff1a;绑…...

【真题笔记】21年系统架构设计师案例理论点总结

【真题笔记】21年系统架构设计师案例理论点总结 从机器学习定义的灵活性和学习算法的可扩展性,对解释器+管道过滤器+隐式调用进行对比分析!面向对象方法开发软件,建立对象模型+动态模型+功能模型,三者关联关系!数据架构的设计过程包括:数据定义、数据分布、数据管理,三者…...

PostgreSQL的奥秘:深入探究事务与锁的秘密世界

PostgreSQL事务 1. 概述 在数据库系统中&#xff0c;事务&#xff08;Transaction&#xff09;是执行数据库操作的最小逻辑单位。它确保了一组操作的完整性和一致性。事务可以通过显式的 BEGIN、COMMIT 和 ROLLBACK 语句块来控制&#xff0c;也可以在自动提交模式&#xff08…...

Python进行GRPC和Dubbo协议的高级测试

在微服务架构日益流行的今天&#xff0c;分布式系统的复杂性不断增加。GRPC 和 Dubbo 协议作为当今互联网行业中常见的高性能通信协议&#xff0c;已经成为服务之间交互的核心。然而&#xff0c;随着服务调用层次的不断增加&#xff0c;如何有效地测试这两种协议&#xff0c;确…...

全程云OA系统QCPES.asmx存在SQL注入漏洞

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...

从建立TRUST到实现FAIR:可持续海洋经济的数据管理

1. 引言 随着我们对信息管理方式的信任&#xff0c;我们的社会对数字化数据的以来呈指数级增长。为了跟上大数据的需求&#xff0c;通过不断的努力和持续实践&#xff0c;对“good”数据管理方式的共识也在不断发展和演变。 加拿大正在建设国家基础设施和服务以及研究数据管理…...

基于SSM的“汽车销售分析与管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SSM的“汽车销售分析与管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 销售经理系统首页图 客户管理图 车辆销…...

vs2015QT项目添加多语言翻译总结

一、简介 当软件有国际化的需求时&#xff0c;就需要多语言翻译功能&#xff0c;最常见的语言就是支持中文和英语&#xff0c;本文介绍在vs2015QT环境下&#xff0c;进行国际化翻译的具体流程。 二、多语言翻译实现流程 1.底层实现原理介绍 QT写的客户端软件&#xff0c;能…...

替换OpenTSDB和HBase,宝武集团使用IoTDB助力钢铁设备智能运维

时序数据库 IoTDB 应用于宝武集团全基地钢铁时序数据管理&#xff0c;激活数据资产&#xff0c;赋能大型设备智能运维。 1. 背景概述 宝武装备智能科技有限公司&#xff08;以下简称&#xff1a;宝武智维&#xff09;是中国宝武设备智能运维专业化平台公司&#xff0c;30 余年始…...

MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下MathGPT的原理介绍&#xff0c;在中小学数学教学的应用场景&#xff0c;以及代码样例实现。MathGPT的核心架构是一个精心设计的多层次系统&#xff0c;旨在有效处理复杂的数学问题。其主要组成部分包括 数学知识图谱…...

前端框架大比拼:React.js, Vue.js 及 Angular 的优势与适用场景探讨

文章目录 前言一、React.js特点使用方法适用场景 二、Vue.js特点使用方法适用场景 三、Angular特点使用方法适用场景 四、如何选择合适的前端框架五、前端框架对项目性能的影响结语 前言 随着互联网技术的飞速发展&#xff0c;前端开发已经从简单的页面展示演变为复杂的应用构…...

MySQL45讲 第二十讲 幻读是什么,幻读有什么问题?

文章目录 MySQL45讲 第二十讲 幻读是什么&#xff0c;幻读有什么问题&#xff1f;一、幻读的定义二、幻读带来的问题&#xff08;一&#xff09;语义问题&#xff08;二&#xff09;数据一致性问题 三、InnoDB 解决幻读的方法四、总结 MySQL45讲 第二十讲 幻读是什么&#xff0…...

MySQL技巧之跨服务器数据查询:进阶篇-从A数据库复制到B数据库的表中

MySQL技巧之跨服务器数据查询&#xff1a;进阶篇-从A数据库复制到B数据库的表中 基础篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的连接名: MY_ODBC_MYSQ…...

【论文阅读】利用SEM二维图像表征黏土矿物三维结构

导言 在油气储层研究中&#xff0c;黏土矿物对流体流动的影响需要在微观尺度上理解&#xff0c;但传统的二维SEM图像难以完整地表征三维孔隙结构。常规的三维成像技术如FIB-SEM&#xff08;聚焦离子束扫描电子显微镜&#xff09;虽然可以获取高精度的3D图像&#xff0c;但成本…...

可靠UDP协议(KCP)使用说明

希望这篇文章&#xff0c;对学习和使用 KCP 协议的读者&#xff0c;有帮助。 1. KCPUDP 流程图 2. 示例代码&#xff08;待补充&#xff09; #include <iostream>int main() {// TODO: kcp examplereturn 0; }...

ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能

一、简介 本播放器是在vs2019下开发&#xff0c;通过ffmpeg实现拉流解码功能&#xff0c;通过D3D实现视频的渲染功能。截图功能采用libjpeg实现&#xff0c;可以截取jpg图片&#xff0c;图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现&#xff0c…...

【Flink】-- flink新版本发布:v2.0-preview1

目录 1、简介 2、非兼容变更 2.1、API 2.2、连接器适配计划 2.3、配置 2.4、其它 3、重要新特性 3.1、存算分离状态管理 3.2、物化表 3.3、批作业的自适应执行 3.4、流式湖仓 4、附加 4.1、非兼容性的 api 程序变更 4.1.2、Removed Classes # 4.1.3、Modified Cl…...

Node.js 版本管理的最终答案 Volta

文章目录 特点安装Unix系统安装Windows系统安装 常用命令volta fetchvolta installvolta uninstallvolta pinvolta listvolta completionsvolta whichvolta setupvolta runvolta help 建议 目前对于前端项目的node 版本&#xff0c;我们一般会在项目 package.json 的 engines 字…...

蓝桥杯每日真题 - 第11天

题目&#xff1a;&#xff08;合并数列&#xff09; 题目描述&#xff08;14届 C&C B组D题&#xff09; 解题思路&#xff1a; 题意理解&#xff1a;给定两个数组&#xff0c;目标是通过若干次合并操作使两个数组相同。每次合并操作可以将数组中相邻的两个数相加&#xff…...

Vue vs React:两大前端框架的区别解析

在现代前端开发中&#xff0c;Vue.js 和 React.js 是两个最受欢迎的框架和库。我们常常面临选择它们的困惑。虽然这两者在本质上都是为了构建用户界面而设计的&#xff0c;但它们在设计理念、使用方式和生态系统等方面有着显著的区别。今天&#xff0c;我们将通过深入分析这两个…...

【树莓派raspberrypi烧录Ubuntu远程桌面登入树莓派】

提示&#xff1a;本文利用的是Ubuntu主机和树莓派4B开发板&#xff0c;示例仅供参考 文章目录 一、树莓派系统安装下载前准备工作下载安装树莓派的官方烧录软件imagerimager的使用方法 二、主机与树莓SSH连接查看数梅派IP地址建立ssh连接更新树莓派源地址 三、主机端远程桌面配…...

c# 调用c++ 的dll 出现找不到函数入口点

今天在调用一个设备的dll文件时遇到了一点波折&#xff0c;因为多c 不熟悉&#xff0c;调用过程张出现了找不到函数入口点&#xff0c;一般我们使用c# 调用c 文件&#xff0c;还是比较简单。 [DllImport("AtnDll2.dll",CharSet CharSet.Ansi)]public static extern …...

LInux——环境基础开发工具使用(正在更新中...)

1.软件包管理器 Linux下安装软件的方案&#xff1a; 1. 源代码安装 2. rpm包安装 3. 包管理器安装 --- yum/ apt &#xff08;此图片来自于比特就业课课件&#xff09; 1.1 操作生态系统 好的操作系统定义&#xff1a; 生态环境好 不同的操作系统根本是生态不同&#xff08;…...

linux 内核asmlinkage关键字总结

1&#xff0c;看一下asmlinkage的定义 CPP_ASMLINKAGE __attribute__((regparm(0))) GCC中使用__attribute__((regparm(n)))指定最多可以使用n个寄存器&#xff08;eax, edx, ecx&#xff09;传递参数&#xff0c;n的范围是0~3&#xff0c;超过n时则将参数压入栈中&#xff08;…...

⚡️如何在 React 和 Next.js 项目里优雅的使用 Zustand

前言 你是否曾感觉在 React 中管理状态简直是一场噩梦&#xff1f;如果你已经厌倦了不停地处理 props、context 和 hooks&#xff0c;那么现在是时候认识 Zustand 了。Zustand 是一个轻量级的状态管理库&#xff0c;它简化了你处理应用状态的方式。在这篇文章中&#xff0c;我…...

Pinpoint(APM)进阶--Pinot指标采集(System Metric/Inspector)

接上文 Pinpoint使用Pinot进行指标数据存储&#xff0c;Pinot流摄入需要Kafka 本文详解Kafka和Pinot的安装部署&#xff0c;以及Pinpoint的指标采集 Pinot 简介 Apache Pinot是一个实时分布式OLAP数据存储&#xff0c;专为低延迟、高吞吐量分析而构建&#xff0c;非常适合面…...