浅析Python中线程以及线程阻塞
作者:真的不能告诉你我的名字 发布时间:2022-03-06 22:14:23
本文所依赖的环境为:
进程和线程的概念
进程概念
我们想运行一个程序,首先会将该程序从存储介质上通过IO
总线加载进内存中,而后再通过cpu
进行调度。这个时候,我么么将这个正在运行的程序称之为进程,它有内存地址、内存空间、数据栈等等信息,进程之间通信一般称之为IPC
,常见的方法有 管道、消息队列、套接字等。
线程概念
而线程则不同,线程是在进程中运行的,一个进程至少有一个线程。在单个cpu
中,同一时刻一个进程只有一个线程在工作,其他则被挂起,也称之为睡眠。由于线程属于进程,所以会共享进程的内存信息。线程之间通信不仅可以使用共享内存来通信,依然可以使用 如 管道、消息队列、套接字等。
线程优缺点
多线程是一种并发方式,优点为可以同时执行多个任务,用于提升时间和效率。
比如,我们想写一个python
服务器下载电影,一次只能下载一部,若我们使用多线程后,可以一次"同时"下载n
部,从而提升了效率。
但是有些事多线程不能做的,并发冲突是其中一种。比如掘金点赞功能,如果没有对点赞这个变量进行并发控制,可能会出现数据不一致的情况。
在python中如何使用线程
在使用python
写多线程之前,先来看一个小案例,假设我们使用python
写了一个下载电影的程序。
import time
def downloadMovie(i):
print("%s 开始下载编号为%s电影中。。。" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i)))
time.sleep(5)
print("%s 编号为%s电影下载完毕" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i)))
def main():
for i in range(5):
downloadMovie(i)
if __name__ == '__main__':
main()
我们假设模拟下载电影的一个程序,下载过程使用time.sleep
代替。在没有使用多线程的时候,它的执行过程如下:
可以看到,它是顺序执行的,需要等上一部下载完毕,才能开始下载下一部。
如果使用线程来做该需求呢? 我们可以这样来写:
import time
import threading
def downloadMovie(i):
print("%s 开始下载编号为%s电影中。。。" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i)))
time.sleep(5)
print("%s 编号为%s电影下载完毕" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i)))
def main():
for i in range(5):
t = threading.Thread(target=downloadMovie,args=(i,))
t.start()
if __name__ == '__main__':
main()
上述代码,在原始代码基础上,我们引入了threading
库,在循环中使用Thread
来做线程的实例化对象,我们需要传入target
和args
,target
需要传入函数名称,args
需要传入参数,注意这里参数需要传入可迭代的对象,所以当只有一个参数的时候,也需要在后面加一个,
。最后使用start
方法让其开始执行。
运行后的效果如下:
可以发现,我们程序几乎同步的打印下载开始,也几乎同时打印下载完毕。
总结起来发现,我们线程启动一个线程,是不是非常简单呢?只需要引入threading
模块,定义Thread
来做对象,最后使用start()
运行即可。
线程阻塞也很重要
线程直接跑就完了呗,为什么还需要阻塞呢?我们这里做一个简单的需求:上面的代码改改,我们下载完视频后,要压缩一下,由于只讨论线程,所以就只用print
代替操作,我们可以这样操作:
在上面的基础上,我们增加了2个步骤,1: 是将下载好的文件放入列表fileList
中,2. 最后开始遍历fileList
文件,进行压缩,最后打印一个压缩完毕,看起来没什么问题吧?
那我们来运行一下一下呢?
额。。。这个很显然不符合我们的预期,我们还没下载文件完毕,怎么就开始压缩了呢,而且压缩完毕了,再输出的文件下载完毕,这是为什么呢?
这是因为线程在启动后,如果我们不去设置阻塞,他就会一直执行下去,就拿我们刚才的案例来看,我们可以将其理解为:
看上图,我们启动线程后,它就放在后台了,我们就立马执行遍历fileList
步骤,但是这个时候恰恰fileList
是空的,所以我们压缩了空文件,压缩完毕后,文件才下载完毕。
这个时候我们就需要等线程执行完毕之后,再执行下面的语句了,否则执行完了没意义,所以这个时候就需要引入线程阻塞了,我们需要将下载的线程全部执行完毕后,再开始压缩文件,只需要线程增加一个join
方法即可,代码修改如下:
在原先的基础上,我们需要先定义一个线程池,用于放已经执行了的线程,而后再遍历该线程池,每一个都设置阻塞,这样就会等所有线程都执行完毕了,再进行后面的操作,由于我们后面是压缩需要用到前面的结果,所以阻塞是必不可少的,程序执行结果为:
这个流程图可以理解为这样的:
现在你知道阻塞有什么用了吧。
来源:https://juejin.cn/post/7224874901815492668
猜你喜欢
- 把程序放到一个文件中,然后包含再call就可以了。(JMAIL4.3)<%'警告函数sub w_msg(messag
- 在项目开发中,经常出现这样的需求。在新增或修改一个主表数据时,对应的从表也要进行同步,此时我们是怎么操作的了?典型的方法就是对于主表的各数据
- 问题当浏览SQL Server 2008的新特性时,我们看到了透明数据加密。这看起来很有趣。您能为我们解释一下并介绍下执行它的细节吗?专家解
- 说到机器学习,大家首先想到的可能就是Python和算法了,其实光有Python和算法是不够的,数据才是进行机器学习的前提。大多数的数据都会存
- 简介Simon Willison来自英国,是一名经验丰富的开发人员。曾工作于Yahoo,是Web开发框架Django的创始人之一,也是Ope
- 以前做音乐项目的时候,最让我们头痛的就是满足用户的问题。在音乐的领域,不要试图去满足所有用户这个定律得到了最充分的验证。究其原因,无非是音乐
- 序言小学妹说要毕业了,学了一学期Python等于没学,现在要做毕设做不出来,让我帮帮她,晚上去她家吃夜宵。当时我心想,这不是分分钟的事情,还
- 本文实例讲述了Python使用循环神经网络解决文本分类问题的方法。分享给大家供大家参考,具体如下:1、概念1.1、循环神经网络循环神经网络(
- ASP,一种最先广泛的流行在WEB行业的编程语言。严格的说,ASP还算不上的编程语言。不过,因为微软的大力支持,ASP这一路,走得非常顺利。
- 首先忠心感谢凌宇5942给我的帮助!在他的启迪下我发现了另一种实现flash透明背景的办法,愿与大家共同探讨:凌宇5942告知的解决办法:在
- 本文主要介绍python 数据可视化模块 Matplotlib,并试图对其进行一个详尽的介绍。通过阅读本文,你可以:了解什么是 Matplo
- 阅读上一篇:FrontPage XP设计教程3——网页的布局 FrontPage XP可以保证用户设计网页与不同的浏览器兼容,它所提供的样式
- 失效的书签们我们日常浏览网站的时候,时不时会遇到些新奇的东西( 你懂的.jpg ),于是我们就默默的点了个收藏或者加书签。然而当我们面对成百
- 中国,美国,英国3国时间js同步动态显示,对于做企业网站的朋友相信用的到,特别是做英文网站的朋友,加上这一段代码会给你的网站增色不少!本文j
- 工作中偶尔需要做客流分析,用pyplot 库绘图。一般情况下, x 轴刻度默认显示为数字。例如:我希望x 轴刻度显示为星期日期。查询pypl
- 起因前端日子写完的Python入库脚本,通过直接读取配置文件的内容(包含了数据库的ip,数据库的用户名,数据库的密码),因为配置文件中的数据
- 继Go 1.18支持泛型后,Go 将在下个版本中支持pdqsort排序算法再次引起了开发者们的热切讨论。目前,Go仓库的最新commit中提
- Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)
- 今晚开放ecmall商城的QQ登陆功能,在回调时产生错误,file_get_contents函数执行时,没有抓取到正确的信息,于是改用cur
- INSTR的第三个参数为1时,实现的是indexOf功能。 INSTR的第三个参数为-1时,实现的是lastIndexOf功能。 例如: I