• python语法基础-并发编程-进程-进程池以及回调函数


    ###############   进程池    ##############

    """
    
    进程池的概念
    为什么会有进程池?
    1,因为每次开启一个进程,都需要创建一个内存空间,这是耗时的
    2,进程过多,操作调度也会耗时,
    所以会有非常大的性能问题,
    所以我们不会让进程太大,我们会设计一个进程池,
    
    进程池:
    1,Python中先创建一个进程的池子,
    2,这个进程池能存放多少个进程,比如有5个进程,
    3,先把这些进程创建好,
    4,比如有50个任务他们到进程池里面去找进程,找到的就执行,找不到的就等待,
    5,进程执行结束之后,不会结束,而是返回进程池,等待下一个任务,
    所以进程池,可以节省进程创建的时间,节省了操作系统的调度,而且进程不会过多的创建,
    
    所以进程池和信号量有什么关系?
    假设有200个任务,
    信号量,信号量还是200个进程在排队,去拿钥匙,所以不能控制有多少进程,而是控制了同一时间有几个进程在执行,
    也就是只允许5个进程让操作系统调度,节省了操作系统的调度时间,但是并没有节省进程的创建时间,
    而进程池,是有200个任务去拿进程,所以进程池既是节省了操作系统的调度时间,也节省进程的创建时间,
    
    更高级的进程池是比较智能的,
    比如现在进程池有5个进程,就可以处理过来了,就不需要增加
    但是如果处理等待的任务太多了,急需要往进程池里面加进程,一直到设置的进程池上限
    如果任务减少了,就进程池里面减少,
    这是比较智能的,
    
    Python中没有高级的进程池,只有一个固定的进程数的进程池,没有弹性的那种,
    
    """

    进程池的使用:进程池的同步调用:

    import os,time
    from multiprocessing import Pool
    
    def work(n):
        print('%s run' %os.getpid())
        time.sleep(1)
        return n**2
    
    if __name__ == '__main__':
        p=Pool(3) #进程池中从无到有创建三个进程,以后一直是这三个进程在执行任务
        res_l=[]
        for i in range(10):
            res=p.apply(work,args=(i,)) # 同步调用,直到本次任务执行完毕拿到res,等待任务work执行的过程中可能有阻塞也可能没有阻塞
                                        # 但不管该任务是否存在阻塞,同步调用都会在原地等着
            res_l.append(res)
    
        print(res_l)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    进程池的使用:进程池的异步调用:

    import os
    import time
    import random
    from multiprocessing import Pool
    
    def work(n):
        print('%s run' %os.getpid())
        time.sleep(random.random())
        return n**2
    
    if __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

    ###############   进程池的返回值   ##############

    # 进程池的返回值,
    
    from multiprocessing import Pool, Process
    def func(i):
        return i
    # if __name__ == '__main__':
    #     pool = Pool(5)
    #     res_list = []
    #     for i in range(10):
    #         # res = pool.apply(func,args=(i,))  # 所以这个结果接收,就是返回值,
    #         res = pool.apply_async(func,args=(i,))  # 所以这个结果接收,就是返回值,
    #         res_list.append(res)
    #     for res in res_list:
    #         print(res.get())  # get会阻塞等待结果
    
    # 上面讲了apply和apply_async 的返回值的问题,
    # 下面讲讲map的返回值的问题,比较简单
    
    if __name__ == '__main__':
        pool = Pool(5)
        ret = pool.map(func,range(10))
        print(ret)  # 这是返回了一个列表,
    
    # 使用的时候想用map,map搞不定就使用,apply_async

    ###############  进程池的回调函数    ##############

    # 进程池的回调函数
    
    from multiprocessing import Pool
    
    def func1(n):
        print(111)
        return n
    
    def func2(n):
        print(222)
        print(n*2)
    
    if __name__ == '__main__':
        p = Pool(5)
        p.apply_async(func1,args=(10,),callback=func2)
        p.close()
        p.join()
        # 回调函数都是在主进程中执行的,
  • 相关阅读:
    python构造一个freebuf新闻发送脚本
    CISCO路由器练习
    python dns欺骗
    心脏滴血漏洞
    0CTF题中的神奇宝贝WP
    一套海量在线用户的移动端IM架构设计实践分享(含详细图文)(转)
    sendfile函数--零拷贝(转)
    浅谈分布式消息技术 Kafka(转)
    架构之微服务(zookeeper)转
    Zookeeper 3、Zookeeper工作原理(转)
  • 原文地址:https://www.cnblogs.com/andy0816/p/12375729.html
Copyright © 2020-2023  润新知