进程池

Posted qq752059037

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程池相关的知识,希望对你有一定的参考价值。

进程池(Pool)

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。

初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务

一般不会创建太多进程,因为CPU工作量太大,我们一般根据CPU个数创建,CPU个数可以os.cpu_count()获得

import time
from multiprocessing import Pool,Process
def func(num):
    time.sleep(0.2)
    print(%s号进程完毕%num)
#
if __name__ == __main__:
    start = time.time()
    p = Pool(32) #这里指定最大进程数
    for i in range(100):
        p.apply_async(func,args=(i,))  # 异步提交func到一个子进程中执行
    p.close()    # 关闭进程池,用户不能再向这个池中提交任务了
    p.join()     # 阻塞,直到进程池中所有的任务都被执行完
    print(time.time() - start)
#这里我用1个进程:20.7秒 4个进程:6.3秒 8个进程:4.62秒 16个进程:5.6秒 32个进程:7.68秒

注意: 一定要关闭进程池然后join 因为主程序和子程序是完全异步的,不然子程序还没开启,主程序就结束了


 

multiprocessing.Pool常用函数解析:

  • apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
  • close():关闭Pool,使其不再接受新的任务;
  • terminate():不管任务是否完成,立即终止;
  • join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

 

 

提交任务 (获取返回值)

提交任务
同步提交 apply
返回值 : 子进程对应函数的返回值
一个一个顺序执行的,并没有任何并发效果
异步提交 apply_async
没有返回值,要想所有任务能够顺利的执行完毕
p.close()
p.join() # 必须先close再join,阻塞直到进程池中的所有任务都执行完毕
有返回值的情况下
res.get() # get不能再提交任务之后立刻执行,应该是先提交所有的任务再通过get获取结果
map()方法
异步提交的简化版本
自带close和join方法

 

使用apply同步提交

def task(num):
    time.sleep(1)
    print(%s : %s%(num,os.getpid()))
    return num**2
 
if __name__ == __main__:
    p = Pool()
    for i in range(20):
        res = p.apply(task,args=(i,))   # 同步提交,必须等子程序执行完然后打印 才会进行下一个进程
        print(-->,res)

 

 

apply_async异步提交

def task(num):
    time.sleep(1)
    print(%s : %s%(num,os.getpid()))
    return num**2

if __name__ == __main__:
    p = Pool()
    res_lst = [] #先添加进列表,最后再获取返回值
    for i in range(20):
        res = p.apply_async(task,args=(i,))   # 提交任务的方法 异步提交
        res_lst.append(res)
    for res in res_lst:
        print(res.get())

 

 

 

 

map方法

p = Pool() # 创建进程池

p.map(main,range(10))

# 将数组中的每个元素提取出来当作函数的参数,创建一个个进程,放进进程池中 # 第一个参数是函数,第二个参数是一个迭代器,将迭代器中的数字作为参数依次传入函数中

map方法是异步提交的简化版本,自带close和join方法,

返回值为一个列表

def task(num):
    time.sleep(0.3)
    print(%s : %s%(num,os.getpid()))
    return num**2
if __name__ == __main__:
    p = Pool()
    ret=p.map(task,(range(20)))
    for i in ret:
        print(i)

 

以上是关于进程池的主要内容,如果未能解决你的问题,请参考以下文章

多线程编程

在 Python 多处理进程中运行较慢的 OpenCV 代码片段

python进程进程池代码部分

线程池

IIS6 程序池错误< 'DefaultAppPool' 提供服务的进程意外终止>

java 简单的代码片段,展示如何将javaagent附加到运行JVM进程