使用tornado.ioloop.IOLoop.run_in_executor时如何避免线程过多?
How to avoid too many threads when using tornado.ioloop.IOLoop.run_in_executor?
我正在使用 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
,但该线程仍保留在函数 return 之后。我可以在 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: python-tornado@googlegroups.com
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
和 return 一个可等待的 Future
对象。 [1][2][3]
- [1]: https://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.IOLoop.run_in_executor
- [2]: https://www.tornadoweb.org/en/stable/_modules/tornado/ioloop.html#IOLoop.run_in_executor
- [3]: https://docs.python.org/3/library/concurrent.futures.html
线程在函数 return 之后做什么?为什么在 future 对象解析后它们不被杀死?我应该如何避免这种情况?
run_in_executor
将 concurrent.futures.Executor
对象作为第一个参数。
您可以创建一个执行器并限制线程池的大小:
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=8)
IOLoop.current().run_in_executor(executor, slow_func)
我正在使用 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
,但该线程仍保留在函数 return 之后。我可以在 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: python-tornado@googlegroups.com
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
和 return 一个可等待的 Future
对象。 [1][2][3]
- [1]: https://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.IOLoop.run_in_executor
- [2]: https://www.tornadoweb.org/en/stable/_modules/tornado/ioloop.html#IOLoop.run_in_executor
- [3]: https://docs.python.org/3/library/concurrent.futures.html
线程在函数 return 之后做什么?为什么在 future 对象解析后它们不被杀死?我应该如何避免这种情况?
run_in_executor
将 concurrent.futures.Executor
对象作为第一个参数。
您可以创建一个执行器并限制线程池的大小:
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=8)
IOLoop.current().run_in_executor(executor, slow_func)