美文网首页高并发编程
通过多线程/多进程提高任务处理速度

通过多线程/多进程提高任务处理速度

作者: nextbang | 来源:发表于2017-01-10 13:42 被阅读30次

    有的时候一个任务需要进行大量的网络、磁盘或数据库请求,比如后台抓取网页,比如离线数据统计等,完成任务需要多次迭代,每次都会产生网络IO、磁盘IO或数据库连接等待,导致任务执行时间很长。但是,任务又有一个特点,迭代之间不需要顺序执行,这就是多线程/多进程非常适合的场景。

    在python里,因为GIL的限制,导致没有真正的多线程,所以ThereadPool也在官网提示使用multiprocessing来代替。

    This module is OBSOLETE and is only provided on PyPI to support old projects that still use it. 
    Please DO NOT USE IT FOR NEW PROJECTS! 
    Use modern alternatives like the multiprocessing module in the standard library or even an asynchroneous approach with asyncio.
    
    multiprocessing 的简单用法:
    from multiprocessing import Pool
    def f(x): 
        return x*x
    if __name__ == '__main__': 
        with Pool(5) as p: 
            print(p.map(f, [1, 2, 3]))
    

    这种方式,采用的依然是同步顺序执行的方式,发挥多进程威力的异步方式如下:

    from multiprocessing import Pool
    import time
    
    def f(x):
        time.sleep(1)                                                                                                      
        return x,x*x
    
    if __name__ == '__main__':
        res_list = []  
        # apply  
        with Pool(5) as p:
            for i in xrange(1,20):
                res = pool.apply_async(f,[i])
                res_list.append(res)
    
        # print
        for res in res_list:
            print(res.get())
    
        pool.close()
        pool.join()
    

    需要特别注意的几个地方:

    1. res.get() 需要在进程调用完成后,统一获取,否则就是同步方式了
    2. pool.join() 使主进程等待所有子进程完成后,再退出
    3. 需要在join前调用pool.close()
    也可以直接定义Processing
    from multiprocessing import Process
    import os
    import time
    
    def info(title):
        print(title)                                                                                                                                                                                           
        print('module name:', __name__)
        print('parent process:', os.getppid())
        print('process id:', os.getpid())
    
    def f(name):
        time.sleep(1)
        info('function f')
        print('hello', name)
    
    if __name__ == '__main__':
        info('main line')
        for i in xrange(10):
            p = Process(target=f, args=(i,))
            p.start()
            # p.join()
    

    备注:

    1. 通过os.getppid()和os.getpid() 获取父进程及当前进程的ID
    2. 如果希望线程顺序执行,可调用p.join()

    相关文章

      网友评论

        本文标题:通过多线程/多进程提高任务处理速度

        本文链接:https://www.haomeiwen.com/subject/raykbttx.html