博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进程池和multiprocess.Pool模块
阅读量:4509 次
发布时间:2019-06-08

本文共 4023 字,大约阅读时间需要 13 分钟。

一、为什么要有进程池

  首先,创建进程需要消耗时间,销毁进程也需要时间。其次,即使开启了成千上万的进程,操作系统也不能让它们同时执行,这样反而会影响程序的效率。因此我们不能无限制的根据任务开启或者结束进程。

进程池:定义了一个池子,在里面放上固定数量的进程,有需求来了,就拿这个池中的一个进程来处理任务,等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待认为。如果有许多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。

总结:也就是说,池中进程的数量是固定的,那么同一时间最多有固定数量的进程再运行。这样 不会增加操作系统的调度难度,还节省了开闭进程的时间,也一定程度上能够实现并发效果。

二、进程池和多进程效率对比

import osimport timeimport randomfrom multiprocessing import Poolfrom multiprocessing import Processdef func(i):    i += 1if __name__ == '__main__':    p = Pool(5)          # 创建了5个进程    start = time.time()    p.map(func,range(1000))      p.close()   # 是不允许再向进程池中添加任务    p.join()    print(time.time() - start)  # 0.35544490814208984    start = time.time()    l = []    for i in range(1000):        p = Process(target=func,args=(i,))  # 创建了一百个进程        p.start()        l.append(p)    [i.join() for i in l]    print(time.time() - start)  #  101.00088691711426
import os,timefrom multiprocessing import Pooldef work(n):    print('%s run' %os.getpid())    time.sleep(3)    return n**2if __name__ == '__main__':    p=Pool(3) #进程池中从无到有创建三个进程,以后一直是这三个进程在执行任务    res_l=[]    for i in range(10):        res=p.apply(work,args=(i,)) # 同步调用,直到本次任务执行完毕拿到res,等待任务work执行的过程中可能有阻塞也可能没有阻塞                                    # 但不管该任务是否存在阻塞,同步调用都会在原地等着    print(res_l)
进程池的同步调用
import osimport timeimport randomfrom multiprocessing import Pooldef work(n):    print('%s run' %os.getpid())    time.sleep(random.random())    return n**2if __name__ == '__main__':    p=Pool(3) #进程池中从无到有创建三个进程,以后一直是这三个进程在执行任务    res_l=[]    for i in range(10):        res=p.apply_async(work,args=(i,)) # 异步运行,根据进程池中有的进程数,每次最多3个子进程在异步执行                                          # 返回结果之后,将结果放入列表,归还进程,之后再执行新的任务                                          # 需要注意的是,进程池中的三个进程不会同时开启或者同时结束                                          # 而是执行完一个就释放一个进程,这个进程就去接收新的任务。          res_l.append(res)    # 异步apply_async用法:如果使用异步提交的任务,主进程需要使用jion,等待进程池内任务都处理完,然后可以用get收集结果    # 否则,主进程结束,进程池可能还没来得及执行,也就跟着一起结束了    p.close()    p.join()    for res in res_l:        print(res.get()) #使用get来获取apply_aync的结果,如果是apply,则没有get方法,因为apply是同步执行,立刻获取结果,也根本无需get
进程池的异步调用

 

通过进程池利用socket实现并发聊天

#Pool内的进程数默认是cpu核数,假设为4(查看方法os.cpu_count())#开启6个客户端,会发现2个客户端处于等待状态#在每个进程内查看pid,会发现pid使用为4个,即多个客户端公用4个进程from socket import *from multiprocessing import Poolimport osserver=socket(AF_INET,SOCK_STREAM)server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)server.bind(('127.0.0.1',8080))server.listen(5)def talk(conn):    print('进程pid: %s' %os.getpid())    while True:        try:            msg=conn.recv(1024)            if not msg:break            conn.send(msg.upper())        except Exception:            breakif __name__ == '__main__':    p=Pool(4)    while True:        conn,*_=server.accept()        p.apply_async(talk,args=(conn,))        # p.apply(talk,args=(conn,client_addr)) #同步的话,则同一时间只有一个客户端能访问
server端
from socket import *client=socket(AF_INET,SOCK_STREAM)client.connect(('127.0.0.1',8080))while True:    msg=input('>>: ').strip()    if not msg:continue    client.send(msg.encode('utf-8'))    msg=client.recv(1024)    print(msg.decode('utf-8'))
client端

 

import osimport timefrom multiprocessing import Pool# 参数 概念 回调函数def func(i):    # 多进程中的io多,    print('子进程%s:%s'%(i,os.getpid()))    return i*'*'def call(arg):   # 回调函数是在主进程中完成的,不能传参数,只能接受多进程中函数的返回值    print('回调 :',os.getpid())    print(arg)if __name__ == '__main__':    print('---->',os.getpid())    p = Pool(5)    for i in range(10):        p.apply_async(func,args=(i,),callback=call)    p.close()    p.join()
回调函数

如果在主进程中等待进程池中所有任务都执行完毕后,再统一处理结果,则无需回调函数。

from multiprocessing import Poolimport time,random,osdef work(n):    time.sleep(1)    return n**2if __name__ == '__main__':    p=Pool()    res_l=[]    for i in range(10):        res=p.apply_async(work,args=(i,))        res_l.append(res)    p.close()    p.join() #等待进程池中所有进程执行完毕    nums=[]    for res in res_l:        nums.append(res.get()) #拿到所有结果    print(nums) #主进程拿到所有的处理结果,可以在主进程中进行统一进行处理
无需回调函数

 

转载于:https://www.cnblogs.com/huangjm263/p/8418200.html

你可能感兴趣的文章
关于求最大公约数
查看>>
为Linux配置常用源:epel和IUS
查看>>
天府地
查看>>
C#高级编程
查看>>
JS实现从照片中裁切自已的肖像
查看>>
使用 https://git.io 缩短 a GitHub.com URL.
查看>>
Python:yield关键字
查看>>
EasyRTSPClient:基于live555封装的支持重连的RTSP客户端RTSPClient
查看>>
MySQL巡检
查看>>
学习笔记之传说中的圣杯布局
查看>>
共享内存的设计
查看>>
2017-2018-1 20155203 20155204 实验二 固件程序设计
查看>>
数据可视化视频制作
查看>>
mysql 数据备份。pymysql模块
查看>>
FactoryMethod模式——设计模式学习
查看>>
Android中 AsyncTask
查看>>
原码、反码、补码和移码
查看>>
SQL存储过程与函数的区别
查看>>
@Resource和@Autowired区别
查看>>
VS2010打开就自动关闭问题解决
查看>>