线程池 , 多进程和多线程效率的比较
在一个池子里,放固定数量的线程,这些线程等待任务,一旦有任务来,就有线程自发的去执行任务。
IO密集型可以用多线程,计算密集型适合用多进程
线程池模块:
from concurrent.futures import ThreadPoolExecutor
线程池代码:
from concurrent.futures import ThreadPoolExecutor import time def func(n): for i in range(n): i+=1 print(i) t=ThreadPoolExecutor(20) #开20个线程 start=time.time() t.map(func,range(1000)) #提交多个任务给池中 t.shutdown() #执行 print(time.time()-start)
下面三组代码比较多进程和多线程效率的对比以及总结:
Pool 进程池的效率:
from multiprocessing import Pool from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def func1(num): for r in range(num): r+=1 print(r) if __name__=='__main__': p=Pool(5) #多进程的开启个数,一般是本机核数加一,所以这里是开5个进程 start=time.time() #记下开启进程的时间 p.apply_async(func1,args=(1000,)) #把需要的参数传给进程 p.close() #用了p.apply_async() 就需要用close()和join() p.join() #执行进程 print(time.time()-start) #程序执行结束的时间减去开启进程时的时间
多进程 ProcessPoolExecutor 的效率:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def func1(num): for r in range(num): r+=1 print(r) if __name__=='__main__': #开多进程固定写法 t=ProcessPoolExecutor(5) #多进程的开启个数,一般是本机核数加一,所以这里是开5个进程 start=time.time() #记下开启进程时的时间 for i in range(1000): t.submit(func1,i) #把需要的参数传给进程 t.shutdown() #执行进程 print(time.time()-start) #计算程序开启到结束的时间
多线程 ThreadPoolExecutor 的效率:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def func1(num): for r in range(num): r+=1 print(r) t=ThreadPoolExecutor(20) #开启线程,开启多线程一般是本机核数乘以五,所以这里开启20个线程 start=time.time() #记下开启线程时的时间 t.map(func1,range(1000)) #把需要的参数传给线程 t.shutdown() #执行 print(time.time()-start) #计算程序执行时间
总结: 当涉及计算密集的程序的时候Pool进程池和ProcessPoolExecutor进程池执行效率相当
ThreadPoolExecutor线程池的效率要差很多
所以,当计算密集时,使用多进程,不建议使用多线程
线程池的返回值:
代码:
from concurrent.futures import ThreadPoolExecutor import time def func(num): sum=0 for i in range(num): sum+=i**2 return sum t=ThreadPoolExecutor(20) #开20个线程 ret=t.map(func,range(1000)) #用ret来接返回值,返回的 是一个生成器对象 t.shutdown() #执行线程 print(ret.__next__()) #返回的是一个生成器对象,通过__next__()方法来取返回值 print(ret.__next__()) print(ret.__next__()) print(ret.__next__()) print(ret.__next__())
守护线程:
守护线程模块:
from threading import Thread
from threading import Thread import time def func_daemon(): time.sleep(2) print('守护线程') def func(): time.sleep(1) print('普通线程') if __name__=='__main__': t=Thread(target=func_daemon,) t.daemon=True t.start() t1=Thread(target=func,) t1.start() print('我是父进程') #守护进程随着父进程代码的结束而结束 time.sleep(5) #加上睡眠时间后守护进程发生变化,父进程执行到这里,代码已经执行结束了,但是程序还没结束,此时守护进程不会随着父进程代码结束而随之结束,此时守护进程会执行
守护进程:
守护进程模块:
from multiprocessing import Process
from multiprocessing import Process import time def func_daemon(): time.sleep(1) print('守护进程') def func1(): time.sleep(2) print('普通进程') if __name__=='__main__': t=Process(target=func_daemon,) t.daemon=True t.start() t1=Process(target=func1,) t1.start() print('父进程') #不加时间,守护进程随着父进程代码结束而结束 time.sleep(2) #加时间之后随着父进程程序执行结束而结束