为什么Flask应用的线程在跳出while循环后仍持续运行?
问题根因
你遇到的现象本质是跨请求的线程控制逻辑完全失效,核心问题有3个:
- 你把
threading.Event实例和工作线程都定义在了视图函数内部,每次请求接口都会创建全新的flag对象和线程对象,不同请求之间的实例完全隔离。你调用start=false时clear的是本次请求新建的flag,对之前start=true时已经启动的老线程持有的flag没有任何影响,老线程的flag一直是set状态,会无限运行。 - 视图函数中调用了
t.join(),会直接阻塞当前请求的响应,直到工作线程执行完毕。如果用Flask默认单线程模式,第一个start=true的请求会直接占满服务资源,后续所有请求都无法被处理。 - 你看到的
done日志是start=false请求新建的线程输出的,这个线程持有的flag一开始就是clear状态,所以直接执行到print('done')就退出了,后面继续输出的running是之前启动的老线程一直没停产生的日志,并不是线程重启了。
修复方案
把控制用的Event实例、工作线程实例都放到全局作用域,保证所有请求共享同一个控制对象,同时避免重复创建线程:
import threading import time from flask import Flask, request app = Flask(__name__) # 全局控制flag和工作线程实例 run_flag = threading.Event() work_thread = None def run(): while run_flag.is_set(): print('running') time.sleep(1) print('done') @app.route('/') def index(): global work_thread status = request.args.get('start', default='false', type=str) if status == 'true': # 避免重复启动线程 if work_thread is None or not work_thread.is_alive(): run_flag.set() work_thread = threading.Thread(target=run) work_thread.start() else: # 停止线程 run_flag.clear() # 可选:等待线程完全退出再返回,不需要可以删掉下面两行 if work_thread and work_thread.is_alive(): work_thread.join() return status if __name__ == '__main__': # 不要开debug模式,否则会启动两个进程导致线程控制失效 app.run(debug=False)
注意事项
- 不要开启Flask的debug模式,debug模式默认会启动重载进程,会存在两个服务进程,全局变量不共享,导致控制逻辑失效。生产环境使用Gunicorn等WSGI服务器时,注意要配置工作进程数为1,或者用跨进程的控制方案(比如Redis存状态)。
- 上述方案仅适用于单进程部署场景,如果是多进程部署,需要用分布式状态存储来替换
threading.Event实现控制。
内容的提问来源于stack exchange,提问作者D Park
相关产品推荐
相关产品推荐

