zoukankan      html  css  js  c++  java
  • as_completed函数用例

    使用ThreadPoolExecutor可以简洁地完成简单多线程任务,获取线程返回值的顺序有两种,一种是按线程创建顺序返回,第二种是按线程完成顺序返回(虽然返回顺序不同,执行时间应该是一样的)。

    按线程创建顺序返回

    import time
    import concurrent.futures
    
    times = [3, 1, 2]
    
    def sleeper(secs):
        time.sleep(secs)
        print('I slept for {} seconds'.format(secs))
        return secs
    
    # returns in the order given
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        print(list(executor.map(sleeper, times)))
    
    # I slept for 1 seconds
    # I slept for 2 seconds
    # I slept for 3 seconds
    # [3, 1, 2]
    

    可以看到如果利用executor.map,其返回结果像是内置的map函数一般,对times执行完后返回times的返回值列表,其位置是一一对应的。

    按线程完成顺序返回

    import time
    import concurrent.futures
    
    times = [3, 1, 2]
    
    def sleeper(secs):
        time.sleep(secs)
        print('I slept for {} seconds'.format(secs))
        return secs
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        futs = [executor.submit(sleeper, secs) for secs in times]
        print([fut.result() for fut in concurrent.futures.as_completed(futs)])
    
    # I slept for 1 seconds
    # I slept for 2 seconds
    # I slept for 3 seconds
    # [1, 2, 3]
    

    简单说明一下as_completed函数,在线程使用中,传入一个futures类列表,会返回一个futures类的迭代器,通过迭代该迭代器可以获得已完成的futures(流畅的python中说的是该函数返回一个迭代器,在future运行结束后产出future)。

    刚学的时候还想过这东西有个P用,给你一个futures类列表给我返回一个futures类的迭代器。但其实还挺有用的,可用作调整结果返回顺序为线程完成顺序。

    有点杠的案例

    在多线程中,如果对一个未完成的futures求result是会阻塞的当前线程的,试想如果你要对线程结果作处理,然而需要处理时间较多的线程在前面,直接迭代futures取结果会阻塞主线程,浪费主线程对线程结果处理的时间(当然你也完全可以直接把处理结果的过程放进每个线程中直接处理再返回)。例如以下情况

    times = [4, 1, 2]
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        start_t = time.time()
        futs = [executor.submit(sleeper, secs) for secs in times]
        for fut in futs:
            #模拟对线程结果作处理
            time.sleep(1)
            print(fut.result())
    
        print(time.time()-start_t)
    

    输出结果如下

    I slept for 1 seconds
    I slept for 2 seconds
    I slept for 4 seconds
    4
    1
    2
    6.034992456436157
    

    可见主线程浪费了一秒,而用as_completed则是如下情况

    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        start_t = time.time()
        futs = [executor.submit(sleeper, secs) for secs in times]
        for fut in concurrent.futures.as_completed(futs):
            #模拟对fut。result()操作所需时间
            time.sleep(1)
            print(fut.result())
        print(time.time()-start_t)
    

    结果如下

    I slept for 1 seconds
    I slept for 2 seconds
    1
    2
    I slept for 4 seconds
    4
    5.031828165054321
    

    使用as_completed会按线程完成的顺序返回,处理结果效率更高。

    future类对于线程和协程来说都差不多,所以上述例子在协程中也很可能适用。

    如有纰漏,欢迎斧正

    参考文献

    https://stackoverflow.com/questions/16276423/pythons-concurrent-futures-iterate-on-futures-according-to-order-of-completi

  • 相关阅读:
    autolayout先进的自动布局工具箱
    iOS7自定义back按钮和pop交互手势
    iOS7开发技巧
    UICollectionView专题
    关于AutoLayout(自动布局)那些事儿
    代码统计利器--CLOC
    vue之指令篇 ps简单的对比angular
    从无到有之webpack+vuerouter的简单例子以及各个属性解释
    关于requestanimationframe
    vim常用指令
  • 原文地址:https://www.cnblogs.com/lymmurrain/p/13807976.html
Copyright © 2011-2022 走看看