问题与解答¶
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:
- 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:
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.
executor = concurrent.futures.ThreadPoolExecutor(8)
See the Asynchronous I/O chapter of the Tornadouser’s guide for more on blocking and asynchronous functions.
我的代码是异步的, 但它不能在两个浏览器标签页上并行运行.¶
即使你是用了异步和非阻塞的控制器, 你会发现在测试过程中可能也会出现问题.流量器将会发现你试图在两个不同的标签页加载同一个页面,这时浏览器会延迟加载第二个页面一直等到第一个页面加载完成. 如果你想要看到异步的效果,请尝试以下两种方法中的任意一个:
- 在url上添加一些参数让请求变得不同. 之前是将http://localhost:8888 在两个标签页中打开, 现在可以尝试在一个标签页中打开 而后在另一个标签页打开 http://localhost:8888/?x=2 .
原文: