python-3.x ThreadPoolExecutor生成的将来不会异步运行

roejwanj  于 2023-02-01  发布在  Python
关注(0)|答案(2)|浏览(169)

我想创建一个在ThreadPoolExecutor上运行的future列表,然后在它们完成评估后立即显示每个future。
预期结果为:每3秒打印0、2、6、12中的每一个。
然而,我在12秒后才得到结果,数字同时显示。

from concurrent.futures import ThreadPoolExecutor
import time

def fnc(x, y):
    time.sleep(3)
    return x*y

futures = []
with ThreadPoolExecutor(max_workers=1) as executor:
    for i in range(0, 4):
        print(f"Submitting {i}")
        futures += [executor.submit(fnc, i, i+1)]

for f in futures:
    print(f.result())
cclgggtu

cclgggtu1#

构建已提交future的列表,然后使用 as_completed() 来了解线程何时完成,其结果何时可用。

from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def fnc(x, y):
    time.sleep(3)
    return x*y

futures = []

with ThreadPoolExecutor() as executor:
    for i in range(0, 4):
        print(f"Submitting {i}")
        futures += [executor.submit(fnc, i, i+1)]
    for future in as_completed(futures):
        print(future.result())
xkftehaa

xkftehaa2#

你在ThreadPoolExecutor上下文管理器外调用result方法,当你退出时,它调用__exit__方法:

def __exit__(self, exc_type, exc_val, exc_tb):
    self.shutdown(wait=True)
    return False

shutdown方法签名为:

shutdown(self, wait=True, *, cancel_futures=False)

医生说:

Args:
     wait: If True then shutdown will not return until all running
           futures have finished executing and the resources used by the
           executor have been reclaimed.
     cancel_futures: If True then shutdown will cancel all pending
           futures. Futures that are completed or running will not be
           cancelled.

我们可以看到,默认情况下,它会等到所有正在运行的future和它们的资源都停止运行,并且cancel_futures默认情况下会得到值False,因此我们不是取消挂起的future。
我们可以通过修改fnc来打印值而不是返回值,并且在ThreadPoolExecutor上下文管理器代码块之后什么也不做来证明这一点:

def fnc(x, y):
    time.sleep(3)
    print(x * y)

futures = []
with ThreadPoolExecutor(max_workers=1) as executor:
    for i in range(0, 4):
        print(f"Submitting {i}")
        futures += [executor.submit(fnc, i, i + 1)]

print("Blah!")

仍然打印值0, 2, 6, 12!,即使我们只将函数提交到执行列表...
通过在上下文管理器中移动for循环块来修复它:

from concurrent.futures import ThreadPoolExecutor
import time

def fnc(x, y):
    time.sleep(3)
    return x*y

futures = []
with ThreadPoolExecutor(max_workers=1) as executor:
    for i in range(0, 4):
        print(f"Submitting {i}")
        futures += [executor.submit(fnc, i, i+1)]
    for f in futures:
        print(f.result())

请注意,设置max_workers=1本质上是强制程序连续运行而不是并发运行,在此程序中,设置max_workers=X将一次打印fncX返回结果。
如果你想在两个结果之间等待3秒钟,那么可以将max_workers设置为1或者完全删除它。如果你想每3秒钟打印两个结果-设置max_workers=2等等。

相关问题