下面的代码通过将总的完成时间返回几乎为零来执行预期的,因为它不等待线程完成每个作业。
import concurrent.futures
import time
start = time.perf_counter()
def do_something(seconds):
print(f'Sleeping {seconds} second(s)...')
time.sleep(seconds)
return f'Done Sleeping...{seconds}'
executor= concurrent.futures.ThreadPoolExecutor()
secs = [10, 4, 3, 2, 1]
fs = [executor.submit(do_something, sec) for sec in secs]
finish = time.perf_counter()
print(f'Finished in {round(finish-start, 2)} second(s)')
但是使用with
命令,它确实会等待:
with concurrent.futures.ThreadPoolExecutor() as executor:
secs = [10, 4, 3, 2, 1]
fs = [executor.submit(do_something, sec) for sec in secs]
为什么? with
在多线程中具有此行为的原因是什么?
concurrent.futures
记录不充分。创建执行程序时,必须将其关闭以终止其线程或进程。该代码将通过向它们推送None
命令,然后等待它们完成来发出信号通知线程退出。在第一种情况下,如果您添加了executor.shutdown()
,则会看到延迟。无论如何,它在那里-程序仍然需要10秒退出。
执行程序可以用作上下文管理器(它作为__enter__
和__exit__
方法)。当它退出“ with”块时,将调用__exit__
,并依次为您执行shutdown
调用。
在concurrent.futures.Executor
语句中使用with
等同于使用Executor.shutdown
后对其进行调用。默认情况下,Executor.shutdown
等待所有任务完成。
shutdown(wait=True) Signal the executor that it should free any
当前待处理的期货完成后使用的资源执行。之后调用Executor.submit()和Executor.map()关闭将引发RuntimeError。
[...]
如果您使用with语句,它将关闭执行器(等待,好像调用Executor.shutdown()并将wait设置为True)[...]