进程池-非阻塞式

1.概述

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程

但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到mutiprocessing模块提供的Pool方法

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

 2.使用进程池(非阻塞式)  

#! /usr/bin/env python
# -*- coding:utf-8 -*-
import os
from multiprocessing import Process, Pool
from random import random
import time


def task(task_name):
    print('开始做任务', task_name)
    start = time.time()
    # 使用sleep
    time.sleep(random()*2)
    end = time.time()
    print('完成任务:{}!用时:{},进程id:{}'.format(task_name, (end-start), os.getpid()))


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['听音乐', '吃饭', '洗衣服', '打游戏', '散步', '看孩子', '做饭']
    for task1 in tasks:
        pool.apply_async(task, args=(task1,))  # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
    pool.close()
    pool.join()   # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
    print('over!')

 

函数解释

  • apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞
  • close()    关闭pool,使其不在接受新的任务。
  • terminate()    结束工作进程,不在处理未完成的任务。
  • join()    主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。

执行说明:

创建一个进程池,并制定进程的数量为5,遍历,有7个任务提交到pool中,但是因为pool指定进程数为3,所以前5个被直接送到进程中执行,当其中一个执行完成后,才空出一个进程处理新的任务:看孩子。因为为非阻塞,主函数会自己执行自个的,不搭理进程的执行。

 

 3.加入回调方法

什么是回调方法?

1.任务完成之后调用的方法

2.回调方法要有参数

 

import os
from multiprocessing import Process, Pool
from random import random
import time


def task(task_name):
    print('开始做任务', task_name)
    start = time.time()
    # 使用sleep
    time.sleep(random()*2)
    end = time.time()
    return '完成任务:{}!用时:{},进程id:{}'.format(task_name, (end-start), os.getpid())


container = []
def callback_func(n):
    container.append(n)


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['听音乐', '吃饭', '洗衣服', '打游戏', '散步', '看孩子', '做饭']
    for task1 in tasks:
        pool.apply_async(task, args=(task1,), callback=callback_func)  # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
    pool.close()
    pool.join()   # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束

    for c in container:
        print(c)
    print('over!')

  

 进程池的好处:

1.可以设置进程的数量

2.可以进程复用(一个进程执行完任务后,可以接着执行下个任务)

  非阻塞的特点:全部添加到队列中,立刻返回,并没有等待其他的进程执行完毕(如把听音乐添加进去之后,并不是等听音乐这个任务执行完成之后,再添加下一个任务,而是,添加完之后,再去添加下一个任务,直到进程池满了),但是回调函数是等待任务完成之后才去调用的。

 

posted @ 2020-05-06 20:13  GumpYan  阅读(295)  评论(0编辑  收藏  举报