深入了解Python的多线程基础
作者:程序员-夏天 发布时间:2021-12-07 18:50:50
线程
线程(Thread
),有时也被称为轻量级进程(Lightweight Process,LWP
),是操作系 * ⽴调度和分派的基本单位,本质上就是一串指令的集合。
⼀个标准的线程由线程id、当前指令指针(PC),寄存器集合和堆栈组成,它是进程中的⼀个实体,线程本身不拥有系统资源,只拥有⼀点⼉在运⾏中必不可少的资源(如程序计数器、寄存器、栈),但它可与同属⼀个进程的其它线程共享进程所拥有的全部资源。线程不能够独⽴执⾏,必须依存在进程中。
多线程
多线程就是使用多个线程同时执行任务,实现了任务的并行执行,从而提高程序运行效率的方法。
试想一下,如果在单个线程内执行多个任务(比如发送网络请求等),如果前面的任务比较耗时,而后面的任务需要等待前面的任务执行完才能执行,这样会影响任务执行效率,那么就可以使用多线程去执行这些任务,任务可以同时进行,那么将大大的提高执行效率。
Python多线程
在Python中,提供了threading模块来实现多进程操作,这个模块是基于较低级的模块 _thread 的基础上建立的,提供了更易用的高级多线程API。
创建线程
可以通过threading模块中的Thread类来创建线程对象。
Thread语法结构:
threading.Thread(group, target, name, daemon)
group
:默认为None(该参数是为了以后实现ThreadGroup类而保留的)target
:在run方法中调用的可调用对象,即线程要执行的任务name
:线程名称,可以不设定,默认为"Thread-N"形式的名称args
:给target指定的函数传递的参数,以元组的⽅式传递kwargs
:给target指定的函数传递命名参数daemon
:默认为None,将显式地设置该线程是否为守护模式。如果是None,线程将继承当前线程的守护模式属性
Thread常用方法
start()
:启动线程,并调用该线程中的run()方法run()
:线程启动时运行的方法,正是它去调用target指定的函数join(timeout=None)
:让当前调用者线程(一般为主线程)等待,直到该线程结束,timeout是可选的超时时间is_alive()
:返回当前线程是否存活
import threading
import time
def work(i):
print("子线程'{}'work正在运行......".format(threading.current_thread().name))
time.sleep(i)
print("子线程'{}'运行结束......".format(threading.current_thread().name))
if __name__ == '__main__':
print("主线程{}启动".format(threading.current_thread().name))
# 获取线程的名称
threads = []
for i in range(5):
t = threading.Thread(target=work, args=(i,))
# 启动线程
threads.append(t)
t.start()
for t in threads:
t.join()
print("主线程结束")
执行结果为:
上述代码中使用t.join()的功能就是让主线程等待所有子线程结束后才结束,如果想设置守护线程(主线程结束,子线程也随之结束,无论任务执行完成与否)的话,可以使用t.daemon = True
。
GIL锁
GIL的全称是Global Interpreter Lock
(全局解释器锁),这个锁最初的设计是为了保证同一份数据不能被多个线程同时修改,每个线程在执行任务的时候都需要先获取GIL,保证同一时刻只有一个线程可以执行,即同一时刻只有一个线程在解释器中运行,因此Python中的多线程是假的多线程,不是真正意义上的多线程。 如果程序中有多个线程执行任务,那么多个线程会被解释器轮流执行,只不过是切换的很快、很频繁,给人一种多线程“同时”在执行的错觉。
线程池
在之前的文章说过,进程有进程池的机制,同样,线程也有线程池。线程池可以在程序启动时就创建自定义数量的空闲的线程,程序只要将一个任务提交给线程池,线程池就会启动一个空闲的线程来执行它。当该任务执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待下一个任务的执行。
multiprocessing.dummy
里面也有一个Pool对象,它其实就是线程的封装,使用起来和multiprocessing
的Pool非常类似。它们api都是通用的,简单地说,multiprocessing.dummy
是multiprocessing
进程池模块复制的一个线程池模块,强调一下,这里线程池也是受到GIL限制的。
使用方式和multiprocessing.Pool一致,具体参考Python进程池。
from multiprocessing.dummy import Pool
import time
def work(i):
print("work'{}'执行中......".format(i))
time.sleep(2)
print("work'{}'执行完毕......".format(i))
if __name__ == '__main__':
# 创建线程池
# Pool(5) 表示创建容量为5个线程的线程池
pool = Pool(5)
for i in range(10):
pool.apply_async(work, (i, ))
pool.close()
pool.join()
来源:https://blog.csdn.net/weixin_50097774/article/details/121443474
猜你喜欢
- Access允许您在数据库表中包含附件。通过利用微软的对象链接和嵌入(OLE)技术,您可以将照片、图表、文档及其他文件存储在您的Access
- 首先对空格宽度的定义:空格,由于每个浏览器处理会有微小的不同,在这里我将可以选中的宽度作为空格的宽度。视觉宽度和可选中的宽度有 0~3px
- 最近项目中需要Python的打包,看到网上也没有很详细的资料,于是做了一些示例程序。研究了一下,Python如何在Windows和Linux
- 一个封装好的JavaScript拖动类,使用方便:<div id="idDrag" style="bor
- 前言反爬虫是网站为了维护自己的核心安全而采取的抑制爬虫的手段,反爬虫的手段有很多种,一般情况下除了百度等网站,反扒机制会常常更新以外。为了保
- 今天给大家讲的是ASP给图片加水印的知识ASP给图片加水印是需要组件的…常用的有aspjpeg和中国人自己开发的wsImage…前者有30天
- ul: unordered lists ol: ordered lists li: Listsol 有序列表:<ol>
- 上几章节我们主要学习了如何读取文章,而主要任务是读取文档中的文本信息,也就是字符串,而图片本身是不可读的文件所以并没有去读取图片。从今天开始
- 异常的本质导引问题在实际工作中,我们遇到的问题都不是完美的,比如:你写某个模块,用户输入不一定符合你的要求:你的程序要打开某个文件,这个文件
- 下面一段代码给大家带来了python实现12306登录功能,具体代码如下所示:#!/usr/bin/env pythonimport req
- #!/usr/local/bin/php -q author:freemouse <?php // 下面是说明. print (&qu
- 这不是什么原创,是我跟据OReilly.JavaScript.The.Definitive.Guide.5th.Edition.Aug.20
- ES Module导出仅导出named exports: 命名导出,每次可以导出一个或者多个。default exports: 默认导出,每
- 本文实例讲述了PHP实现的DES加密解密类定义与用法。分享给大家供大家参考,具体如下:今天写App接口的时候需要传递加密数据给APP端,于是
- 代码如下:td=date() '此次为设置当前日期,主要是为了调试方便,实际应用中可以使用当天日期.. str=
- 当然,这些并非真正的定律,而只是一些有益的忠告,使你免陷于使用层时可能的困顿中。原来有九条定律的,我们精简掉一条,还有下面的八条:1. 如果
- 之前用Crystal做了一个数字转English Word的Formula刚刚心血来潮, 大半个晚上写了JS版本的数字转换, 由于JS的Bu
- 背景:用python画AR模型的时序图。结果:代码:import numpy as npimport matplotlib.pyplot a
- 按照惯例,年底的淘宝的确是到了“需要改版的时候”。这次新版的淘宝首页上线,乍看并没有多少夺人眼球的地方,但仔细揣摩其中的细节,还是发现了不少
- Logistic Regression Classifier逻辑回归主要思想就是用最大似然概率方法构建出方程,为最大化方程,利用牛顿梯度上升