进程池
就像tcp套接字的listen一样,服务器并不能同时大量的的处理连接请求,所以有了listen来使连接请求不超过设定值,处理完一个便有一个加入进来
同样在
操作系统中并发执行的任务通常大于核数
操作系统不可能无线开启进程,进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)
例如当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个。。。手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
我们就可以通过维护一个进程池来控制进程数目,比如httpd的进程模式,规定最小进程数和最大进程数...
创建一个进程池

from concurrent.futures import ProcessPoolExecutor import time,os def piao(name,n): print("%s is piaoing %s"%(name,os.getpid())) # 打印了进程id time.sleep(1) if __name__ == "__main__": p = ProcessPoolExecutor(4) # 指定进程池最大进程个数 for i in range(10): obj = p.submit(piao,"alex %s"%i,i) # 提交子进程 #运行结果 #alex 0 is piaoing 6136 #alex 1 is piaoing 8872 #alex 2 is piaoing 420 #alex 3 is piaoing 5644 #alex 4 is piaoing 6136 #alex 5 is piaoing 8872 #alex 6 is piaoing 420 #alex 7 is piaoing 5644 #alex 8 is piaoing 6136 #alex 9 is piaoing 8872 #进程ID始终就是四个,另外注意,这里写的都是停一秒,所以他们每次都运行完四个。 #事实上进程池是有一个进程执行完之后,就有一个进程补进来
当有操作需要在子进程都结束之后执行时,就会需要一个类似于join()的操作

from concurrent.futures import ProcessPoolExecutor import time,os,random def piao(name,n): print("%s is piaoing %s"%(name,os.getpid())) # 打印了端口号 time.sleep(random.randint(2,3)) if __name__ == "__main__": p = ProcessPoolExecutor(4) # 指定进程池最大进程个数 for i in range(10): obj = p.submit(piao,"alex %s"%i,i) # 提交子进程 p.shutdown(wait=True) # 在没有这句话的情况下,肯定会先执行下面的操作 # 这句话的意思是进程池中不会再添加进程,等到进程池中的进程运行结束后执行下面的代码 print("哈哈哈哈") #运行结果 #alex 0 is piaoing 12000 #alex 1 is piaoing 904 #alex 2 is piaoing 6120 #alex 3 is piaoing 8328 #alex 4 is piaoing 904 #alex 5 is piaoing 8328 #alex 6 is piaoing 12000 #alex 7 is piaoing 6120 #alex 8 is piaoing 904 #alex 9 is piaoing 8328 #哈哈哈哈
子进程有返回值-result()

#提交/调用任务的方式有两种: #同步调用:提交/调用一个任务,然后就在原地等着,等到该任务执行完毕拿到结果,再执行下一行代码 #异步调用: 提交/调用一个任务,不在原地等着,直接执行下一行代码,结果? from concurrent.futures import ProcessPoolExecutor import time,os,random def piao(name,n): print("%s is piaoing %s"%(name,os.getpid())) # 打印了端口号 time.sleep(random.randint(2,3)) return n*2 if __name__ == "__main__": p = ProcessPoolExecutor(4) # 指定进程池最大进程个数 objs = [] for i in range(10): # 这属于同步调用,要等到obj拿到结果后才会执行之后的代码 # obj = p.submit(piao,"alex %s"%i,i).result() # print(obj) # 异步调用 obj = p.submit(piao,"alex %s"%i,i) # 这里只提交进程,并不拿到他们的结果,并且把进程赋值给一个变量 objs.append(obj) # 把进程追加进列表中 for obj in objs: print(obj.result()) # 从列表中拿到进程的返回值 # 这里提交进程时并不会遇到阻塞,进程池中的四个进程是同时运行的,一个进程运行完,就会有另一个进程开始运行 # 在拿结果的时候可能有一个没有运行完但他后面的就运行完了,他不会跳过去取结果,会等待结果出来,这时后面的 # 结果是计算出来的所以不用等待就能拿到结果 p.shutdown(wait=True) print("哈哈哈哈")