python|初始线程以及线程阻塞

简介: python|初始线程以及线程阻塞

本文所依赖的环境为:

image.png


进程和线程的概念


进程概念

我们想运行一个程序,首先会将该程序从存储介质上通过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代替。在没有使用多线程的时候,它的执行过程如下:

image.png


可以看到,它是顺序执行的,需要等上一部下载完毕,才能开始下载下一部。

如果使用线程来做该需求呢? 我们可以这样来写:

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来做线程的实例化对象,我们需要传入targetargstarget需要传入函数名称,args需要传入参数,注意这里参数需要传入可迭代的对象,所以当只有一个参数的时候,也需要在后面加一个,。最后使用start方法让其开始执行。


运行后的效果如下:

image.png

可以发现,我们程序几乎同步的打印下载开始,也几乎同时打印下载完毕。

总结起来发现,我们线程启动一个线程,是不是非常简单呢?只需要引入threading模块,定义Thread来做对象,最后使用start()运行即可。



线程阻塞也很重要


线程直接跑就完了呗,为什么还需要阻塞呢?我们这里做一个简单的需求:上面的代码改改,我们下载完视频后,要压缩一下,由于只讨论线程,所以就只用print代替操作,我们可以这样操作:

image.png


在上面的基础上,我们增加了2个步骤,1: 是将下载好的文件放入列表fileList中,2. 最后开始遍历fileList文件,进行压缩,最后打印一个压缩完毕,看起来没什么问题吧?

那我们来运行一下一下呢?

image.png


额。。。这个很显然不符合我们的预期,我们还没下载文件完毕,怎么就开始压缩了呢,而且压缩完毕了,再输出的文件下载完毕,这是为什么呢?


这是因为线程在启动后,如果我们不去设置阻塞,他就会一直执行下去,就拿我们刚才的案例来看,我们可以将其理解为:

image.png

看上图,我们启动线程后,它就放在后台了,我们就立马执行遍历fileList步骤,但是这个时候恰恰fileList是空的,所以我们压缩了空文件,压缩完毕后,文件才下载完毕。


这个时候我们就需要等线程执行完毕之后,再执行下面的语句了,否则执行完了没意义,所以这个时候就需要引入线程阻塞了,我们需要将下载的线程全部执行完毕后,再开始压缩文件,只需要线程增加一个join方法即可,代码修改如下:

image.png


在原先的基础上,我们需要先定义一个线程池,用于放已经执行了的线程,而后再遍历该线程池,每一个都设置阻塞,这样就会等所有线程都执行完毕了,再进行后面的操作,由于我们后面是压缩需要用到前面的结果,所以阻塞是必不可少的,程序执行结果为:

image.png


这个流程图可以理解为这样的:

image.png


现在你知道阻塞有什么用了吧。



总结


今天介绍了一下python的多线程,这里只是简单的使用threading库,在python中,多线程的库不仅于此,还有threadQueue等。最后举了一个很简单的例子来说明线程阻塞的重要性。



相关文章
|
2月前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
26天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
1月前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
60 4
|
20天前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
54 0
|
2月前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
2月前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
2月前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
35 3
|
2月前
|
并行计算 安全 Java
Python 多线程并行执行详解
Python 多线程并行执行详解
74 3
|
2月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
70 0
|
2月前
|
Python
告别阻塞,拥抱未来!Python 异步编程 asyncio 库实战指南!
高效处理并发任务对提升程序性能至关重要,Python 的 `asyncio` 库提供了强大的异步编程支持。通过 `async/await` 关键字,可以在等待操作完成时不阻塞程序执行,显著提高效率和响应性。`asyncio` 支持定义异步函数、创建任务、等待多个任务完成等功能,并能结合第三方库如 `aiohttp` 实现异步网络请求。此外,它还支持异常处理,确保异步代码的健壮性。借助 `asyncio`,您可以轻松构建高性能、响应迅速的应用程序。
44 0