Python并发编程:多线程实现的两种方式
bigegpt 2024-12-19 11:30 4 浏览
引言
从这篇文章开始,我们开始把Python中的并发编程模型的支持来逐一介绍。首先是Python中关于多线程编程的支持,也就是基于threading模块来介绍如何进行多线程编程。
本文的主要内容有:
1、Thread类的常用方法
2、实现自定义线程的两种方式
Thread类的常用方法
在Python中要实现多线程编程,最简单的方式就是基于threading模块的Thread类来实现,首先来看下该类中的常用方法。
1、__init__()方法
关于Thread类的初始化方法__init__(),从定义中可以看到:
1、参数target:是一个很核心的参数,用于实现线程要执行的主体业务逻辑,该参数接收一个可调用对象,通常可以是一个函数的引用。
2、参数args:是线程在执行时调用target参数时,需要传入的参数列表,必须是一个元组。
3、参数name:用于自定义线程的名称,默认情况下,每个线程都会有一个形式为“Thread-N"的唯一的名称,为了更好地辨别执行的每个自定义线程,建议指定自定义名称。
4、当我们通过继承Thread类来实现自定义线程类,重载__init__()方法时,必须首先调用Thread类的__init__()方法。
2、run()方法
run()方法是线程中的核心方法,该方法的逻辑代表了线程所承载的业务行为。从文档中可以看出,Thread类的默认run()方法,是实现__init__()方法中所传递的target这个可调用对象的调用操作,同时将args作为参数传递。
如果自定义Thread的子类,通常应该实现该方法的重载,通常的做法是在run()方法中直接编写线程所要实现的业务功能。
需要注意的是,run()方法不应该被直接调用,而是通过Thread对象的start()方法来进行间接调用,否则只是简单的方法在当前线程中的执行,而非新建线程。
3、start()方法
start()方法,用于启动一个线程对象的执行,需要注意的是,该方法最多只能被调用一次,该方法的调用,会将该线程对象的run()方法安排在一个控制线程中等待被调用。
4、join()方法
当某个线程对象的join()方法被调用时,则当前正在执行的线程的执行会被阻塞,直到调用了join()方法的线程对象执行完成才会继续执行。
该方法通常用于进行多个线程之间执行的组织、编排。
5、setDaemon()方法
该方法用于将一个线程设置为守护线程。从文档中,可以看到该方法已经被标记废弃了,后续应当使用daemon这个属性来进行守护线程的设置。
需要说明的有:
1)所谓守护线程是指在后台运行的线程,它存在的目的是为其他非守护线程(也就是用户线程)提供一些支持和服务。
2)当所有的非守护线程都终止时,守护线程会自动终止。
实现自定义线程的两种方式
了解了Thread类中常用的方法之后,我们来看看在Python中实现多线程编程的两种方式(在其他语言中,也基本是类似的方式)。
1、直接使用Thread来实例化线程对象
这种方式主要通过以下步骤来实现:
1)自定义函数封装线程要实现的业务行为。
2)将自定义函数作为target参数,相应的函数实参作为args参数,调用Thread的__init__()方法,来实例化线程对象。
3)调用线程对象的start()方法来启动子线程的执行。
直接看代码:
from threading import Thread
import time
lines = 0
def code(name, n):
global lines
print(f'{name}开始写代码')
for i in range(n):
print(f'{name}写完{i + 1}行代码')
lines += 1
time.sleep(1)
print(f'{name}代码编写完成')
if __name__ == '__main__':
frontend_coder = Thread(target=code, args=('前端', 10))
backend_coder = Thread(target=code, args=('后端', 10))
start_time = time.time()
frontend_coder.start()
backend_coder.start()
frontend_coder.join()
backend_coder.join()
print(f'总共写了{lines}行代码, 共计耗时{time.time() - start_time}秒')
代码的执行结果:
2、自定义Thread类的子类来自定义线程对象
这种方式来实现多线程主要有以下步骤:
1)自定义类继承自Thread类
2)重载__init__()方法,用于实现相关自定义属性、参数的初始化。在__init__()方法中,记得要首先调用Thread类的__init__()方法。
3)重载run()方法,实现自定义线程的业务功能主体。
直接看代码:
from threading import Thread
import time
lines = 0
class CoderThread(Thread):
def __init__(self, coder, line):
super().__init__()
self.coder = coder
self.line = line
def run(self):
global lines
print(f'{self.coder}开始写代码')
for i in range(self.line):
print(f'{self.coder}写完{i + 1}行代码')
lines += 1
time.sleep(1)
print(f'{self.coder}代码编写完成')
if __name__ == '__main__':
frontend_coder = CoderThread('前端', 10)
backend_coder = CoderThread('后端', 10)
start_time = time.time()
frontend_coder.start()
backend_coder.start()
frontend_coder.join()
backend_coder.join()
print(f'总共写了{lines}行代码, 共计耗时{time.time() - start_time}秒')
执行结果与第一种方式完全一样,这里就不贴出来了。
3、两种方法的比较
直观来看,第一种方式似乎更加简洁,所以,初学者通常会更倾向于使用第一种方式。其实,两种方式各有其适用的场景。
实例化Thread对象的方式,更加适用于简单的并发任务,不需要进行复杂的状态管理。语法简单、代码量少、能够快速实现并发任务。但是,缺点是对于复杂的逻辑或者状态管理不够灵活。
通过继承Thread类来实现多线程的方式,更加适用于需要封装复杂逻辑或者状态管理的并发任务。灵活性高、易于扩展和重用、代码的组织更加模块化。但是,缺点就是语法相对复杂,需要编写一些样板代码。
总结
本文简单介绍了threading模块中的Thread类中的常用方法,介绍了在Python中基于threading模块实现多线程编程的两种方式,并对这两种方式做了一个简单的比较。在多种方法的选择中,我们要遵循的首要原则还是”选择最适合当前业务场景的方法“。没有最好,只有更适合。
以上就是本文的全部内容了,感谢您的拨冗阅读,希望对您学习Python并发编程有所帮助。
相关推荐
- 了解Linux目录,那你就了解了一半的Linux系统
-
大到公司或者社群再小到个人要利用Linux来开发产品的人实在是多如牛毛,每个人都用自己的标准来配置文件或者设置目录,那么未来的Linux则就是一团乱麻,也对管理造成许多麻烦。后来,就有所谓的FHS(F...
- Linux命令,这些操作要注意!(linux命令?)
-
刚玩Linux的人总觉得自己在演黑客电影,直到手滑输错命令把公司服务器删库,这才发现命令行根本不是随便乱用的,而是“生死簿”。今天直接上干货,告诉你哪些命令用好了封神!喜欢的一键三连,谢谢观众老爷!!...
- Linux 命令速查手册:这 30 个高频指令,拯救 90% 的运维小白!
-
在Linux系统的世界里,命令行是强大的武器。对于运维小白而言,掌握一些高频使用的Linux命令,能极大提升工作效率,轻松应对各种系统管理任务。今天,就为大家奉上精心整理的30个Linu...
- linux必学的60个命令(linux必学的20个命令)
-
以下是Linux必学的20个基础命令:1.cd:切换目录2.ls:列出文件和目录3.mkdir:创建目录4.rm:删除文件或目录5.cp:复制文件或目录6.mv:移动/重命名文件或目录7....
- 提高工作效率的--Linux常用命令,能够决解95%以上的问题
-
点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...
- 15 个实用 Linux 命令(linux命令用法及举例)
-
Linux命令行是系统管理员、开发者和技术爱好者的强大工具。掌握实用命令不仅能提高效率,还能解锁Linux系统的无限潜力,本文将深入介绍15个实用Linux命令。ls-列出目录内容l...
- Linux 常用命令集合(linux常用命令全集)
-
系统信息arch显示机器的处理器架构(1)uname-m显示机器的处理器架构(2)uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DM...
- Linux的常用命令就是记不住,怎么办?
-
1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...
- Linux常用文件操作命令(linux常用文件操作命令有哪些)
-
ls命令在Linux维护工作中,经常使用ls这个命令,这是最基本的命令,来写几条常用的ls命令。先来查看一下使用的ls版本#ls--versionls(GNUcoreutils)8.4...
- Linux 常用命令(linux常用命令)
-
日志排查类操作命令查看日志cat/var/log/messages、tail-fxxx.log搜索关键词grep"error"xxx.log多条件过滤`grep-E...
- 简单粗暴收藏版:Linux常用命令大汇总
-
号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部下午好,我的网工朋友在Linux系统中,命令行界面(CLI)是管理员和开发人员最常用的工具之一。通过命令行,用户可...
- 「Linux」linux常用基本命令(linux常用基本命令和用法)
-
Linux中许多常用命令是必须掌握的,这里将我学linux入门时学的一些常用的基本命令分享给大家一下,希望可以帮助你们。总结送免费学习资料(包含视频、技术学习路线图谱、文档等)1、显示日期的指令:d...
- Linux的常用命令就是记不住,怎么办?于是推出了这套教程
-
1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...
- Linux的30个常用命令汇总,运维大神必掌握技能!
-
以下是Linux系统中最常用的30个命令,精简版覆盖日常操作核心需求,适合快速掌握:一、文件/目录操作1.`ls`-列出目录内容`ls-l`(详细信息)|`ls-a`(显示隐藏文件)...
- Linux/Unix 系统中非常常用的命令
-
Linux/Unix系统中非常常用的命令,它们是进行文件操作、文本处理、权限管理等任务的基础。下面是对这些命令的简要说明:**文件操作类:*****`ls`(list):**列出目录内容,显...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)