进程是多个资源的集合
线程就是进程里面具体干活的
线程和线程之间是相互独立的
多线程:适用于IO密集型任务
多进程:适用于CPU密集型任务
一、多线程
线程需要使用threading模块
启动线程的方法:
threading.Thread(target=XXX,args=('xxx','xxx')) #target接的是函数名,args接的是传递的参数,如果只有一个参数要这么写args=('xxx',)
通过threading.Thread实例出来的线程都是子线程,只有最先开始的一个线程是主线程
写一个简单的多线程
import threading def down_load(): time.sleep(1) print('运行完了') for i in range(5): #循环5次,即启动5个线程 t=threading.Thread(target=down_load) #实例化一个线程 t.start() #启动线程 print(threading.active_count()) #查看当前线个程数 print(threading.current_thread())#查看当前线程
如果说我现在想看一下启动的线程全部执行完要多久,这就涉及到线程等待,线程等待是用join,使用jion会比较麻烦,可以用一个while循环的方式来处理。
import threading import time def down_load(): time.sleep(1) print('运行完了') start_time=time.time() for i in range(5): #循环5次,即启动5个线程 t=threading.Thread(target=down_load) #实例化一个线程 t.start() #启动线程 while threading.active_count()!=1: #判断线程个数不等于1就一直循环,直到等于1,结束循环 pass print(threading.active_count()) #查看当前线程个数 print(threading.current_thread())#查看当前线程 end_time=time.time() print('时间:',end_time-start_time)
例子:
分别用单线程和多线程两种方式来看一下下载图片的执行时间:
mport requests,time,threading from hashlib import md5 def down_load_pic(url): req = requests.get(url) m = md5(url.encode()) with open( m.hexdigest()+'.png','wb') as fw: fw.write(req.content) url_list = ['http://www.nnzhp.cn/wp-content/uploads/2019/10/f410afea8b23fa401505a1449a41a133.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/481b5135e75c764b32b224c5650a8df5.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/b23755cdea210cfec903333c5cce6895.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/542824dde1dbd29ec61ad5ea867ef245.png'] # 串行运行方式下载(单线程) # start_time=time.time() # for url in url_list: # down_load_pic(url) # end_time=time.time() # # print(end_time-start_time) #并行的方式(多线程) start_time=time.time() for url in url_list: t=threading.Thread(target=down_load_pic,args=(url,)) #只有一个参数要这么写(url,) t.start() while threading.activeCount()!=1: pass end_time=time.time() print(end_time-start_time)
- 线程池
线程池需要使用threadpool模块,需手动安装一下:pip install threadpool
线程池可以自动计算分配数据,不需要我们手动start,还是以下载图片为例:
import threadpool import requests,time,threading from hashlib import md5 def down_load_pic(url): req = requests.get(url) m = md5(url.encode()) with open( m.hexdigest()+'.png','wb') as fw: fw.write(req.content) url_list = ['http://www.nnzhp.cn/wp-content/uploads/2019/10/f410afea8b23fa401505a1449a41a133.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/481b5135e75c764b32b224c5650a8df5.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/b23755cdea210cfec903333c5cce6895.png', 'http://www.nnzhp.cn/wp-content/uploads/2019/11/542824dde1dbd29ec61ad5ea867ef245.png'] pool=threadpool.ThreadPool(20) #实例化一个线程池 reqs=threadpool.makeRequests(down_load_pic,url_list)#分配数据,第一个是函数名,第二个是数据 # [pool.putRequest(req) for req in reqs] #列表生成式,同下面2行代码 for req in reqs: pool.putRequest(req) pool.wait() #等待,都执行完才打印end,如果不等待会先打印end print('end')
- 守护线程
守护线程依赖于主线程,主线程结束,守护线程会立刻结束。
import threading,time def down_load(): time.sleep(1) print('运行完了') for i in range(5): t=threading.Thread(target=down_load) t.setDaemon(True) #设置子线程为守护线程 t.start() print('over')
- 线程锁
多个线程操作同一个数据的时候,就要加锁,
import threading num=0 lock =threading.Lock()#申请一把锁 def add(): global num # lock.acquire()#加锁 # num+=1 # lock.release()#解锁,如果不加锁后不解锁就会出现死锁 with lock:#简写,用with也会帮你自动加锁,解锁 num+=1
for i in range(10): t=threading.Thread(target=add) t.start() while threading.activeCount()!=1: pass print('over:',num)
二、多进程
进程使用multiprocessing模块
import multiprocessing,time def down_load(): time.sleep(1) print('运行完了') if __name__ == '__main__': #windows下多进程需要在main下写,否则会报错,mac不需要 for i in range(5): p=multiprocessing.Process(target=down_load) #实例化一个进程 p.start() while len(multiprocessing.active_children())!=0: pass print(multiprocessing.current_process()) #查看当前进程 # print(multiprocessing.cpu_count()) #查看cpu个数 print('end')