擅长:python、mysql、java
<p>问题是将<code>ThreadPoolExecutor.map</code>的结果转换为列表。如果不这样做,而是直接在生成的生成器上迭代,结果仍按原始顺序生成,但循环在所有结果就绪之前继续。可以通过以下示例对此进行测试:</p>
<pre><code>import time
import concurrent.futures
e = concurrent.futures.ThreadPoolExecutor(4)
s = range(10)
for i in e.map(time.sleep, s):
print(i)
</code></pre>
<p>保持这个顺序的原因可能是因为有时候你得到的结果和你给地图的顺序一样重要。结果可能不会包装在将来的对象中,因为在某些情况下,如果需要的话,在列表上执行另一个映射可能需要太长时间才能获得所有结果。毕竟,在大多数情况下,下一个值很可能在循环处理第一个值之前就准备好了。这在本例中演示:</p>
<pre><code>import concurrent.futures
executor = concurrent.futures.ThreadPoolExecutor() # Or ProcessPoolExecutor
data = some_huge_list()
results = executor.map(crunch_number, data)
finals = []
for value in results:
finals.append(do_some_stuff(value))
</code></pre>
<p>在本例中,<code>do_some_stuff</code>可能需要比<code>crunch_number</code>更长的时间,如果真是这样,那么在保持map的易用性的同时,性能损失并不大。</p>
<p>另外,由于工作线程(/processes)从列表的开头开始处理,并一直工作到您提交的列表的末尾,因此结果应该按照迭代器已经生成的顺序完成。这意味着在大多数情况下<code>executor.map</code>是很好的,但是在某些情况下,例如,如果处理值的顺序无关紧要,并且传递给<code>map</code>的函数需要非常不同的时间来运行,那么<code>future.as_completed</code>可能会更快。</p>