• 进程池-非阻塞式


    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.可以进程复用(一个进程执行完任务后,可以接着执行下个任务)

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

  • 相关阅读:
    Android项目实战(四):ViewPager切换动画(3.0版本以上有效果)
    安卓开发_浅谈ListView(SimpleAdapter数组适配器)
    ADB server didn't ACK 解决方法
    安卓开发_浅谈自定义组件
    Go语言基础之指针
    Go语言基础之接口
    Go语言标准库之fmt
    Go语言基础之函数
    LeetCode go
    Go语言基础之变量和常量
  • 原文地址:https://www.cnblogs.com/GumpYan/p/12838615.html
Copyright © 2020-2023  润新知