我有一个程序,当前正在使用current.current.futures.ThreadPoolExecutor并发运行多个任务。这些任务通常受I/O约束,涉及对本地数据库和远程REST API的访问。但是,这些任务本身可以分为子任务,这也将从并发中受益。

我希望的是,在任务中使用并发.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()

尽管这个玩具示例似乎可行,但我还是希望这是故意的。我希望是这样,因为否则,如果执行程序还使用并发.futures来利用并发性,那么使用执行程序执行任意代码将是不安全的。

最佳答案

从其他线程生成线程绝对没有问题。您的情况也是如此。

但是,迟早产生线程的开销会很高,而产生更多线程实际上会导致软件速度降低。

我强烈建议您使用 asyncio 之类的库,该库可以漂亮地异步处理任务。它是通过使用一个具有非阻塞io的线程来实现的。结果比一般线程的结果甚至更快,因为开销要小得多。

如果您不想使用asyncio,为什么不在main内部创建另一个池执行程序,并将其传递给outer()函数呢?这样,您将拥有最多10个(2x5)的线程,而不是25(5x5)个线程,这更合理吗?

您不能传递将main()调用到outer()的同一outer()执行程序,因为这可能会导致死锁(每个outer()等待另一个outer()完成,然后才能安排inner())。

关于python - 嵌套current.futures.ThreadPoolExecutor,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44989473/

10-12 21:14