该文档不保证在哪个线程回调中运行。唯一记录在案的保证是回调将在属于添加回调的进程的线程中运行,但这可能是任何线程,因为您使用的是 ThreadPoolExecutor 而不是ProcessPoolExecutor:
添加的可调用对象按照它们添加的顺序被调用,并且总是在属于添加它们的进程的线程中调用。
在当前的 ThreadPoolExecutor 实现中,回调执行的线程取决于Future
添加回调时的状态,以及是否Future
取消。这些是实现细节;你不应该依赖它们,因为它们在不同的 Python 实现或不同的版本中可能会有所不同,并且它们可能会随时更改,恕不另行通知。
如果您在Future
完成后添加回调,回调将在您调用的任何线程中执行add_done_callback
。您可以通过查看add_done_callback
源代码来看到这一点:
def add_done_callback(self, fn):
"""Attaches a callable that will be called when the future finishes.
Args:
fn: A callable that will be called with this future as its only
argument when the future completes or is cancelled. The callable
will always be called by a thread in the same process in which
it was added. If the future has already completed or been
cancelled then the callable will be called immediately. These
callables are called in the order that they were added.
"""
with self._condition:
if self._state not in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]:
self._done_callbacks.append(fn)
return
fn(self)
如果状态Future
指示它被取消或完成,fn
则立即在当前执行线程中调用。否则,它会添加到回调的内部列表中,以便在Future
完成时运行。
例如:
>>> def func(*args):
... time.sleep(5)
... print("func {}".format(threading.current_thread()))
>>> def cb(a): print("cb {}".format(threading.current_thread()))
...
>>> fut = ex.submit(func)
>>> func <Thread(Thread-1, started daemon 140084551563008)>
>>> fut = e.add_done_callback(cb)
cb <_MainThread(MainThread, started 140084622018368)>
如果一个future被一个成功的cancel
调用取消,那么执行取消的线程会立即调用所有的回调:
def cancel(self):
"""Cancel the future if possible.
Returns True if the future was cancelled, False otherwise. A future
cannot be cancelled if it is running or has already completed.
"""
with self._condition:
if self._state in [RUNNING, FINISHED]:
return False
if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
return True
self._state = CANCELLED
self._condition.notify_all()
self._invoke_callbacks()
return True
否则,回调由执行未来任务的线程调用。