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

  • 相关阅读:
    tomcat发布的class中有一部分类会生成同名的XXX$1.class
    报错:The method encodeBase64String(byte[]) is undefined for the type Base64
    bootstrap中的fileInput上传文件时,文件名称中有-(中划线)改为了_下划线
    java中去html/jsp等前台页面 造成的空格
    # 50 个最常被问到的 Selenium 面试问题和答案
    # 为什么测试人员学习测试自动化(仍然)如此困难
    # 如何引进高级的 IT 自动化项目:一个 3 步走计划
    **Selenium IDE、Selenium RC 和 WebDriver 之间有什么区别?**
    pandas 数据分析好的博文
    pandas contains 函数
  • 原文地址:https://www.cnblogs.com/lymmurrain/p/13807976.html
Copyright © 2011-2022 走看看