我有一个程序,我目前正在使用concurrent.futures.ThreadPoolExecutor并发运行多个任务。这些任务通常是I/O绑定的,包括对本地数据库和远程REST的访问。但是,这些任务本身也可以分为子任务,这也将受益于并发性。
我希望在任务中使用concurrent.futures.ThreadPoolExecutor是安全的。我编写了一个玩具例子,这个例子似乎很有效:
import concurrent.futures
def inner(i, j):
return i, j, i**j
def outer(i):
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(inner, i, j): j for j in range(5)}
results = []
for future in concurrent.futures.as_completed(futures):
results.append(future.result())
return results
def main():
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(outer, i): i for i in range(10)}
results = []
for future in concurrent.futures.as_completed(futures):
results.extend(future.result())
print(results)
if __name__ == "__main__":
main()
虽然这个玩具例子似乎有效,但我希望有一些信心,这是故意的。我希望是这样,因为否则使用executor执行任意代码是不安全的,如果它也使用concurrent.futures来利用并发性。
发布于 2018-06-30 08:33:18
从其他线程产生线程是绝对没有问题的。你的案子没什么不同。
但是迟早,产生线程的开销会相当高,并且产生更多的线程实际上会导致您的软件慢下来。
我强烈建议使用像https://docs.python.org/3/library/asyncio.html这样的库,它能够很好地异步处理任务。它通过使用一个具有非阻塞io的线程来做到这一点。结果可能是比普通线程更快的,因为开销要小得多。
如果不希望使用异步,为什么不在main中创建另一个池执行器,并将其传递给outer()
函数?这样,而不是25 (5x5)线程,您将有最多10 (2x5),这是更合理的吗?
您不能传递同一个main()
执行器,该执行器调用outer()
到outer()
,因为它可能导致死锁(由每个outer()
在调度inner()
之前等待另一个outer()
完成)。
https://stackoverflow.com/questions/44989473
复制