本文介绍了Tornado 多线程中的多个 IOLoop的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在多个线程中运行多个 IOLoop,我想知道 IOLoop 的实际工作原理.

I am trying to run multiple IOLoop in multiple threads and I am wondering how the IOLoop actually works.

class WebThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, name='WebThread')

    def run(self):
        curdir = os.path.dirname(os.path.realpath(__file__))

        application = Application() #Very simple tornado.web.Application
        http_server_api = tornado.httpserver.HTTPServer(application)
        http_server_api.listen(8888)

        logging.info('Starting application')

        #tornado.ioloop.IOLoop.instance() is singleton, not for thread, right?

        ioloop = tornado.ioloop.IOLoop()
        ioloop.make_current()
        ioloop.start()

根据文档,我不能使用 IOLoop.instance() 因为它是一个单例并且我在一个线程中工作.所以我创建了自己的 IOLoop.但是这段代码监听了8888端口却无法渲染任何网页.我想知道是否遗漏了什么,或者我是否需要以某种方式将 http_server 绑定到 IOLoop?

According to the doc, I can not use IOLoop.instance() since it's a singleton and I am working in a thread. So I created my own IOLoop. But this piece of code listens on the port 8888 but can not render any web page. I am wondering is there anything missed, or do I need to tie the http_server to the IOLoop in some way?

此外,我发现删除最后 3 行并替换为 tornado.ioloop.IOLoop.instance().start 非常适合单线程.但是单例和自创IOLoop有什么区别呢?

Also, I find that removing the last 3 lines and substitute with tornado.ioloop.IOLoop.instance().start works perfectly for single thread. But what's the difference between the singleton and self created IOLoop?

我是 Tornado 的新手,欢迎提供任何答案.

I am new to Tornado and any answers are welcomed.

推荐答案

IOLoop.current 不带参数返回已创建线程的ioloop 或调用IOLoop.instance().而HTTPServer(实际上在TCPServer中)使用IOLoop.current与ioloop交互,所以你唯一应该改变的是在HTTPServer之前创建ioloop,例如

IOLoop.current without params returns already created ioloop of thread or it calls IOLoop.instance(). And HTTPServer (actually in TCPServer) use IOLoop.current to interact with ioloop, so the only thing you should change is to create ioloop before HTTPServer e.g.

class WebThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, name='WebThread')

    def run(self):
        curdir = os.path.dirname(os.path.realpath(__file__))

        ioloop = tornado.ioloop.IOLoop()

        application = Application() #Very simple tornado.web.Application
        http_server_api = tornado.httpserver.HTTPServer(application)
        http_server_api.listen(8888)

        logging.info('Starting application')

        ioloop.start()

我也删除了 IOLoop.make_current,因为它是多余的 - IOLoop() 将 self 设置为当前.

Also I've removed IOLoop.make_current, since it's redundant - IOLoop() sets self as a current.

上面的代码可以工作,但只能使用一个线程,因为默认情况下不启用重用端口.你最终会得到:

Code above will work, but only with one thread, because reuse_port is not enabled by default. You will end up with:

OSError: [Errno 98] Address already in use

您可以使用

    http_server_api.bind(port=8888, reuse_port=True)
    http_server_api.start()

代替http_server_api.listen(8888)

这篇关于Tornado 多线程中的多个 IOLoop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:39