我想根据条件限制线程数,而不会阻止主线程,因为主要线程正在运行一个烧瓶应用程序。
该应用程序的端点可触发子流程中的某些作业,每个作业都在自己的线程中运行。在该过程结束时,将在数据库中更新条目。为简单起见,我们假设它正在执行的命令只是一个普通的echo $something
。以下部分代码:
# job_runner.py
import threading
import subprocess
def popen_with_callback(self, echo):
"""Run subprocess in a separate thread.
starts subprocess in a separate thread --> adds new entry to the jobs table
--> updates jobs.return_code on completion --> returns thread
"""
def run_in_thread(echo):
command = [
"bash", "-c",
"for ((i=0;i<100;i=i+1)); do echo %s; sleep 1; done" %(echo)
]
proc = subprocess.Popen(
command,
shell=False
)
# add job to database
models.Job.create_job(proc.pid, ..., ...)
proc.wait()
# update job return code on exit
models.Job.update_return_code(proc.returncode, ...)
thread = threading.Thread(target=run_in_thread, args=(echo))
thread.daemon = True
thread.start()
return thread
假设我的端点只接受一个参数,并基于此,它将该参数作为参数触发popen_with_callback
。
# some_view.py
from . import job_runner
@app.route('/run_job', methods=['POST'])
def run_job():
data = request.get_json()
echo = data['echo']
job_runner.popen_with_callback(echo)
所以这种方法工作正常,因为主线程继续运行应用程序并且作为仅运行os进程的线程触发作业,因此应用程序本身没有重负载。
问题是,实际上一些运行的命令是CPU密集型的,我想在调用这样的作业时限制并发线程。因此,我们假设贪婪的资源称为i_use_cpu_like_crazy
,其他资源称为easy_peasy
。
我想将使用大量CPU的进程数量限制为只有一个,而不关心可能的其他进程,但我无法理解如何在不阻塞主线程的情况下实现这种机制,可能使用Queue
,Pool
,Semaphore
...
这个想法如下:
curl -X POST -H "Content-type: application/json" http://localhost:5000/run_job -d '{"echo": "i_use_cpu_like_crazy"}'
1)如果还有另一个进程i_use_cpu_like_crazy
已经运行,请将此新进程添加到队列中,并在正在运行的进程完成时触发它
curl -X POST -H "Content-type: application/json" http://localhost:5000/run_job -d '{"echo": "easy_peasy"}'
2)只需创建线程并运行该过程而不进行任何检查