多线程中的Tornado多个IOLoop

时间:2016-07-28 19:16:14

标签: python multithreading tornado

我试图在多个线程中运行多个IOLoop,我想知道IOLoop实际上是如何工作的。

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?

另外,我发现删除最后3行并用tornado.ioloop.IOLoop.instance().start代替完全适用于单线程。但单身人士和自我创造的IOLoop有什么区别?

我是Tornado的新手,欢迎任何答案。

1 个答案:

答案 0 :(得分:4)

  

一般来说,在构造异步对象时应该使用IOLoop.current作为默认值,并且当你想要从另一个主线程与主线程进行通信时使用IOLoop.instance。

没有参数的

IOLoop.current会返回已经创建的线程的ioloop ,或者它会调用IOLoop.instance()。而HTTPServer(实际上在TCPServer中)使用IOLoop.current与ioloop进行交互,所以你应该改变的唯一方法是在HTTPServer之前创建ioloop,例如

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()将自设置为当前。

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

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)