一.进程池 (同步 异步 返回值)
缺点:
开启进程慢
几个CPU就能同时运行几个程序 进程的个数不是无线开启的
应用:
100个任务
进程池
如果必须用多个进程
且是高计算型 没有IO型的程序
希望并行 最充分的使用CPU
示例:
import os import time from multiprocessing import Pool def func1(): time.sleep(2) print(os.getpid(),i) if __name__=="__main__"": p=Pool(5) for i in range(100): p.apply_async(func=func1,args=(i,)) p.close() p.join() print("主进程结束")
1. 同步请求 获取返回值
import os import time from multiprocessing import Pool,Process def haha(num): time.sleep(0.5) print(os.getpid(),num) return True if __name__=="__main__": p=Pool(5) for i in range(20): ret=p.apply(func=haha,args=(i,)) print(ret)
结果:一个一个的显示打印内容和返回值
2. 异步请求 不获取返回值
import os import time from multiprocessing import Pool,Process def haha(num): time.sleep(0.5) print(os.getpid(),num) if __name__=="__main__": p=Pool(5) for i in range(20): p.apply_async(func=haha,args=(i,)) p.close() p.join()
结果五个五个的显示打印内容
3. 异步请求 获取返回值
import os import time from multiprocessing import Pool,Process def haha(num): time.sleep(1) print(os.getpid(),num) return True if __name__=="__main__": r_l=[] p=Pool(5) for i in range(20): ret=p.apply_async(func=haha,args=(i,)) r_l.append(ret) p.close() p.join() for ret in r_l: print(ret.get())
结果 等待所有任务都执行完毕之后再统一获取结果
异步 apply_async总结1:
如果需要主进程等待,需要p.join
但是join的行为是依赖close
4. 异步请求 获取返回值 一个任务执行完毕之后就可以获取到一个结果(顺序是按照提交任务的顺序)
import os import time from multiprocessing import Pool,Process def haha(num): time.sleep(5) print(os.getpid(),num) return True if __name__=="__main__": r_l=[] p=Pool(5) for i in range(20): ret=p.apply_async(func=haha,args=(i,)) r_l.append(ret) for ret in r_l: print(ret.get())
结果:一个任务执行完毕之后就可以获取到一个结果(顺序是按照提交任务的顺序)
异步 apply_async总结2.
如果函数有返回值: 可以通过ret.get()来获取返回值 但是如果一边提交一边获取返回值会让程序变成同步 所以要想保留异步的效果应该将返回对象保存在列表中,所有任务提交完成之后再来取结果. 这种方式也可以去掉join,来完成主进程的阻塞等待池中的任务执行完毕 如果是异步的提交任务,那么任务提交之后进程池和主进程也异步了, 主进程不会自动等待进程池中的任务执行完毕.
二.回调函数
import os import time import random from multiprocessing import Pool def haha(num): time.sleep(3) print("pid :",os.getpid(),num) return num def back(arg): print("callback :",os.getpid(),arg) if __name__=="__main__": print("主进程",os.getpid()) p=Pool(5) for i in range(20): ret=p.apply_async(func=haha,args=(i,),callback=back) p.close() p.join() #需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了额,你可以处理我的结果了。 # 主进程则调用一个函数去处理该结果,该函数即回调函数
进程总结:
import os import time import random from multiprocessing import Pool def haha(num): time.sleep(3) print("pid :",os.getpid(),num) return num def back(arg): print("callback :",os.getpid(),arg) if __name__=="__main__": print("主进程",os.getpid()) p=Pool(5) for i in range(20): ret=p.apply_async(func=haha,args=(i,),callback=back) p.close() p.join() #需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了额,你可以处理我的结果了。 # 主进程则调用一个函数去处理该结果,该函数即回调函数
三.进程与线程对比:
进程
是计算机中最小的资源分配单位
在利用多个CPU执行的过程中,对多个程序的资源进行管理和隔离
进程的弊端
开启和关闭 以及 切换 都会带来很大的时间开销
过多的进程还会造成操作系统调度的压力
线程
线程是CPU调度的最小单位
每个进程中至少有一个线程
实际上执行代码的是线程
线程属于进程
进程负责获取操作系统分配给我的资源
线程负责执行代码
从代码的角度上看:
多进程:
开启和结束 时间花销大
切换的效率低
内存隔离
多线程:
开启和结束 时间开销非常小
切换效率高
内存不隔离
Cpython解释器下的全局解释器锁
在同一个进程中的多个线程在同一时刻只能有一个线程访问CPU
多线程无法形成并行
锁的线程
什么时候才会用到CPU
程序计算的时候
IO阻塞
是不会用到CPU的
Jpython解释器就没有全局解释器锁
pypy解释器没有全局解释器锁
4CPU
起四个进程
进程里起线程
四.Threading模块
示例: import os import time from threading import Thread def func(): time.sleep(3) print(123,os.getpid()) print(456,os.getpid()) for i in range(10): Thread(target=func).start() time.sleep(3)