问题与解答¶

    Fetch this handler twice at the same time and you’ll see that the secondfive-second countdown doesn’t start until the first one has completelyfinished. The reason for this is that is a blockingfunction: it doesn’t allow control to return to the so that otherhandlers can be run.

    Of course, is really just a placeholder in these examples,the point is to show what happens when something in a handler gets slow.No matter what the real code is doing, to achieve concurrency blockingcode must be replaced with non-blocking equivalents. This means one of three things:

      • Find a coroutine-friendly equivalent. For time.sleep, use instead:

      When this option is available, it is usually the best approach.See the Tornado wikifor links to asynchronous libraries that may be useful.

      class CoroutineTimeoutHandler(RequestHandler):
      .coroutine
      def get(self):
      io_loop = IOLoop.current()
      for i in range(5):
      print(i)
      yield gen.Task(io_loop.add_timeout, io_loop.time() + 1)

      Again, theTornado wikican be useful to find suitable libraries.

      • Run the blocking code on another thread. When asynchronous librariesare not available, can be usedto run any blocking code on another thread. This is a universal solutionthat can be used for any blocking function whether an asynchronouscounterpart exists or not:

      executor = concurrent.futures.ThreadPoolExecutor(8)


    See the Asynchronous I/O chapter of the Tornadouser’s guide for more on blocking and asynchronous functions.

    我的代码是异步的, 但它不能在两个浏览器标签页上并行运行.¶

    即使你是用了异步和非阻塞的控制器, 你会发现在测试过程中可能也会出现问题.流量器将会发现你试图在两个不同的标签页加载同一个页面,这时浏览器会延迟加载第二个页面一直等到第一个页面加载完成. 如果你想要看到异步的效果,请尝试以下两种方法中的任意一个:

    原文: