我有一个程序,我目前正在使用concurrent.futures.ThreadPoolExecutor同时运行多个任务。这些任务通常受I / O限制,涉及对本地数据库和远程REST API的访问。但是,这些任务本身可以分成子任务,这也可以从并发中受益。
我希望在任务中使用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()
尽管这个玩具示例似乎有效,但我还是有信心这是故意的。我希望它是,因为否则使用执行程序执行任意代码是不安全的,以防它也使用concurrent.futures来利用并发。
答案 0 :(得分:0)
从其他线程生成线程绝对没有问题。您的情况也是如此。
尽管迟早会产生很多线程,但是产生更多的线程实际上会使您的软件变慢。
我强烈建议使用类似 asyncio 的库,该库可以漂亮地异步处理任务。它通过使用一个具有非阻塞io的线程来实现。结果可能会比普通线程甚至更快,因为开销要小得多。
如果您不想使用asyncio,为什么不在main内部创建另一个池执行程序,并将其传递给outer()
函数呢?这样,您将拥有最多10个(2x5)的线程,而不是25(5x5)个线程?
您不能传递将main()
调用到outer()
的同一outer()
执行程序,因为这可能会导致死锁(每个outer()
等待另一个outer()
进入在他们可以安排inner()
之前完成。