进程池

就像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("哈哈哈哈")
接收子进程的返回值

 

posted @ 2017-11-30 18:14  瓜田月夜  阅读(145)  评论(0)    收藏  举报