Python 的线程池
的回调函数
是在主线程
还是工作线程
中运行的?
from concurrent.futures import ThreadPoolExecutor
import threading
def action():
return ''
def callback_func(future):
print(threading.current_thread().name)
# assert 'ThreadPoolExecutor' in threading.current_thread().name
# assert 'MainThread' in threading.current_thread().name
pool = ThreadPoolExecutor(max_workers=10)
for i in range(10):
future = pool.submit(action)
future.add_done_callback(callback_func)
输出如下:
MainThread
ThreadPoolExecutor-0_1
ThreadPoolExecutor-0_1
MainThread
ThreadPoolExecutor-0_3
ThreadPoolExecutor-0_3
ThreadPoolExecutor-0_3
MainThread
ThreadPoolExecutor-0_1
ThreadPoolExecutor-0_1
从 print
的结果来看,有一些是在 MainThread
中,有一些是在 ThreadPoolExecutor
执行 callback_func
函数
这这这??????
如果加点时延,又全在 ThreadPoolExecutor 中执行回调函数了:
from concurrent.futures import ThreadPoolExecutor
import threading
import time
def action():
time.sleep(1)
return ''
def callback_func(future):
print(threading.current_thread().name)
# assert 'ThreadPoolExecutor' in threading.current_thread().name
# assert 'MainThread' in threading.current_thread().name
pool = ThreadPoolExecutor(max_workers=10)
for i in range(10):
future = pool.submit(action)
future.add_done_callback(callback_func)
输出如下:
ThreadPoolExecutor-0_5
ThreadPoolExecutor-0_0
ThreadPoolExecutor-0_7ThreadPoolExecutor-0_3
ThreadPoolExecutor-0_6
ThreadPoolExecutor-0_1
ThreadPoolExecutor-0_9
ThreadPoolExecutor-0_8
ThreadPoolExecutor-0_2
ThreadPoolExecutor-0_4
python 中是 master thread 执行 callback 还是 work thread 负责执行 callback?
我们先来看看在 python 的线程池中是如何添加回调函数的吧!
可以看到:
这就有一个问题,如果 func_get 执行很快很快,还没来的及 add_done_callback 就执行完成,那这个时候 add_done_callback(func_callback) ,这个 func_callback 还会被执行吗?
答案是会得!
为什么呢?
一起来看看线程池的源码吧!
使用 submit 之后,会返回一个 Future 实例
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/thread.py
随后调用 Future 实例的 add_done_callback 方法
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/_base.py
可以看到,很简单:
_state
已经是 CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED 这些状态中的任何一个了, 就说明线程池已经把这个任务做完了,这个时候,主线程会去执行 callback 任务。call_back 列表列表中的任务,会在 work thread 干完 feature 对应的正事之后执行,这个时候是在 workthread 中执行的。
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/_base.py
_invoke_callbacks
会在cancel
、set_result
、set_exception
这三中情况末尾执行/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/concurrent/futures/_base.py
总结:
建议:
所以要小心,不要在 callback 中执行可能会导致长时间阻塞的任务