1.基础知识
1)进程
系统中正在运行的应用程序
每个进程之间是独立的,分配专用且受保护的内存空间
2)线程
进程要执行任务,必须要有线程(每个进程至少有一条线程)
进程(程序)的所有任务都在线程中执行(线程是进程的执行单元)
1个线程中任务的执行是串行的(如果线程中有多个任务,只能一个一个的执行)
3)多线程
一个进程中可以开启多条线程,多条线程可以并行(同时)执行不同的任务(每个任务只能被一个线程执行)
原理:
同一时间,cpu只能处理1条线程
多线程并发(同时)执行,其实是cpu快速地在多条线程之间调度(切换)
cpu调度速度足够快,就造成多线程并发的假象
耗时操作:
耗时操作放到主线程中,会阻塞线程
阻塞时间为多个耗时操作的耗时之和
可用多线程解决耗时操作
2.多线程技术
python内置的threading模块,可以支持多线程
所有的进程默认都有一个线程(该线程为主线程),其他线程叫子线程
如果想在进程中添加其他线程,就创建线程对象
def download(file):
print('开始下载:',file)
time.sleep(5)
print(file,':下载完成')
if __name__ == '__main__':
print('aaaaaaa')
#1.创建子线程对象
'''
方法一:
创建线程对象
target:需要在子线程中需要执行的函数
args:给函数(target)传参
'''
t1=threading.Thread(target=download,args=['爱情公寓'])
#2.在子线程中执行任务
t1.start()
t2=threading.Thread(target=download,args=['狄仁杰'])
t2.start()
download('rensiy')
t3=threading.Thread(target=input,args=['>>>'])
t3.start()
print('======')
3.多线程技术2
方式2:写一个自己的线程类
写一个类继承Tread类
重写run方法,在里面规定需要在子线程中执行的任务实现在子线程中执行的任务对应的功能,如果需要参数,通过类的对象属性来传值
from threading import Thread
from requests import request
import re
from random import randint
# 下载数据
class DownloadTread(Thread):
'''下载类'''
def __init__(self,file_path):
super().__init__()
self.file_path=file_path
def run(self):
'''
1.run方法的内容就是在子线程中执行的内容,
2.该方法不要直接调用
'''
print('开始下载')
response=request('GET',self.file_path)
data=response.content
# 获取文件后缀
suffix=re.search(r'\.\w+$',self.file_path).group()
num=str(randint(1,1000))
with open('./git'+num+suffix,'wb')as f:
f.write(data)
print('下载完成')
if __name__ == '__main__':
print('=====')
t1=DownloadTread('http://10.7.181.117/shareX/Git.exe')
#通过start间接调用run方法,run方法中的任务在子线程中执行
t1.start()
#直接调用run方法,run方法中的任务在当前线程中执行
# t1.run()
#传图片
t2=DownloadTread('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1533720058151&di=766b5c97653351e805c85881ecaa57d0&imgtype=0&src=http%3A%2F%2Fx.itunes123.com%2Fuploadfiles%2Fb2ab55461e6dc7a82895c7425fc89017.jpg')
t2.start()
print('!!!!!!!')
4.join函数
from threading import Thread,current_thread
from random import randint
import time
class Download(Thread):
def __init__(self,file):
'''
这儿父类的init方法必须调用,否则当前这个
创建的对象中就没有新的线程
'''
super().__init__()
self.file=file
def run(self):
print('开始下载',self.file)
print(current_thread())
mul=randint(5,10)
time.sleep(mul)
print(self.file,'下载结束')
if __name__ == '__main__':
print('======')
print(current_thread())
# 获取线程
'''
主线程:MaintTread
子线程:Thread-数字(数字从1开始)
'''
start_time=time.time()
t1=Download('最强Z.mp4')
t1.start()
t2=Download('最强.mp4')
t2.start()
# 如果一个任务想要在另一个子线程中的任务执行
# 完成后再执行,就在当前任务前面用子线程对象调用join方法
# 所以join也会阻塞,直到子线程中任务执行完为止
# t2.join()
t1.join()
end_time = time.time()
print('总共消耗时间%.2f'%(end_time-start_time))
======
<_MainThread(MainThread, started 4740)>
开始下载 最强Z.mp4
<Download(Thread-1, started 10500)>开始下载 最强.mp4
<Download(Thread-2, started 9960)>
最强Z.mp4 下载结束
总共消耗时间6.00
最强.mp4 下载结束