python-3.x - 使用tornado.ioloop.IOLoop.run_in_executor时如何避免线程过多?

标签 python-3.x multithreading tornado python-asyncio concurrent.futures

我正在使用tornado.ioloop.IOLoop.run_in_executor将同步函数更改为异步函数,但事实证明,每次调用该函数时,都会创建一个线程,但不会杀死该线程。

这是一个最小的可重现示例(至少在我的机器上可重现):

#!/usr/bin/env python3                                                          

import time
import tornado.ioloop
import tornado.web

def slow_func():
    time.sleep(1)
    print('slow func returned')
    return 'succ\n'

class TestHandler(tornado.web.RequestHandler):
    async def get(self):
        print('GET called')
        try:
            result = await tornado.ioloop.IOLoop.current().run_in_executor(None, slow_func)
        except Exception as e:
            print(e)
        self.write(result)
        print('GET returned')

if __name__ == '__main__':
    tornado.web.Application([
        (r'/', TestHandler),
    ]).listen(3000)
    print('Serving at 3000')
    tornado.ioloop.IOLoop.current().start()

对此 TestHandler 的每个请求都会创建一个新线程来运行 slow_func,但该线程在函数返回后仍然保留。我可以在 ps H 中看到它们,它会创建新线程,直到达到 ulimit。我这里的环境是:

$ uname -a
Linux xxx 2.6.32-754.6.3.el6.x86_64 #1 SMP Tue Sep 18 10:29:08 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux
$ python3 --version
Python 3.7.4
$ pip3 show tornado
Name: tornado
Version: 6.0.3
Summary: Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.
Home-page: http://www.tornadoweb.org/
Author: Facebook
Author-email: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3f4f464b575051124b504d515e5b507f58505058535a584d504a4f4c115c5052" rel="noreferrer noopener nofollow">[email protected]</a>
License: http://www.apache.org/licenses/LICENSE-2.0
Location: /xxx/lib/python3.7/site-packages
Requires: 
Required-by:

tornado.ioloop.IOLoop.run_in_executor 使用 concurrent.futures.Executor 并返回一个可等待的 Future 对象。 [1][2][3]

函数返回后线程在做什么?为什么它们在未来对象解析后没有被杀死?我应该如何避免这种情况?

最佳答案

run_in_executor 采用 concurrent.futures.Executor对象作为第一个参数。

您可以创建一个执行器并限制线程池的大小:

from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=8)

IOLoop.current().run_in_executor(executor, slow_func) 

关于python-3.x - 使用tornado.ioloop.IOLoop.run_in_executor时如何避免线程过多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57707073/

相关文章:

python - 如何将 int 的值与元组列表中的同一组组合?

python - Windows-单击应用程序时 Pyinstaller 错误 “failed to execute script ”

c++ - 将对象传递给另一个线程后无法访问某些成员变量

python - 在 Tornado 中设置时区

python - 在requirements.txt中包含python版本吗?

c++ - 为什么线程创建方法需要一个参数?

c++ - 如何使用 std::thread?

python - 如何使用 pympler 跟踪/修复 tornado-redis 中的内存泄漏?

python - nltk 的 Tornado 多进程崩溃

python - 接受 int 或 int 元组作为 python 函数参数