您正在寻找的是一种在线程组上等待的方法,而 Python 的 API 没有提供这种方法。所以,你必须模拟它。
最简单但效率最低的方法就是忙轮询线程:
while threads:
for thread in threads:
thread.join(timeout=0.1)
if not thread.is_alive():
action(thread)
threads.remove(thread)
break
time.sleep(0.1)
更好的解决方案是使用一个同步对象,所有线程都可以在它们退出之前发出信号。你可以用一个简单的Event:
while threads:
evt.wait()
evt.clear()
for thread in threads:
if not thread.is_alive():
thread.join()
action(thread)
threads.remove(thread)
break
但是,这与任何自重置事件具有相同的潜在竞争条件:您可能会错过触发器。在某些情况下,您可以仔细研究所有细节并确定比赛不会造成任何伤害。如果没有,您必须使用稍微复杂一些的东西,例如 Condition。
或者您可以跳到更高的级别并使用Queue,线程可以在退出之前使用q.put(self)。那么主线程就容易搞定了:
while threads:
thread = q.get()
thread.join()
action(thread)
threads.remove(thread)
但值得考虑的是,您是否真的需要 3 个线程函数,或者 3 个可以在池或执行器上运行的任务函数,或者甚至是 1 个具有 3 个不同参数的任务函数。
例如,对于具有 3 组 args 的单个函数,很难比这更简单:
with multiprocessing.dummy.Pool(3) as pool:
for result in pool.imap_unordered(func, [arg1, arg2, arg3]):
action(result)
或者,对于 3 个功能:
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as ex:
fs = [ex.submit(func) for func in funcs]
for f in concurrent.futures.as_completed(fs):
action(f.result())
或者您甚至可以将action 添加到期货上:
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as ex:
for func in funcs:
ex.submit(func).add_done_callback(action)