Frequently Asked Questions
2015-12-04 11:03
393 查看
转自:http://www.tornadoweb.org/en/stable/faq.html
Frequently Asked Questions
Why isn’t this example withtime.sleep()running in parallel?
My code is asynchronous, but it’s not running in parallel in two browser tabs.
Why isn’t this example with time.sleep()
running in parallel?
Many people’s first foray into Tornado’s concurrency looks something like this:class BadExampleHandler(RequestHandler): def get(self): for i in range(5): print(i) time.sleep(1)
Fetch this handler twice at the same time and you’ll see that the second five-second countdown doesn’t start until the first one has completely finished. The reason for this is that
time.sleepis ablocking function: it doesn’t allow control to return to the
IOLoopso that other handlers can be run.
Of course,
time.sleepis 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 blocking code must be replaced with non-blocking equivalents. This means one of three things:
Find a coroutine-friendly equivalent. For
time.sleep, use
tornado.gen.sleepinstead:
class CoroutineSleepHandler(RequestHandler): @gen.coroutine def get(self): for i in range(5): print(i) yield gen.sleep(1)
When this option is available, it is usually the best approach. See the Tornado wiki for links to asynchronous libraries that may be useful.
Find a callback-based equivalent. Similar to the first option, callback-based libraries are available for many tasks, although they are slightly more complicated to use than a library designed for coroutines. These are typically used with
tornado.gen.Taskas an adapter:
class CoroutineTimeoutHandler(RequestHandler): @gen.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, the Tornado wiki can be useful to find suitable libraries.
Run the blocking code on another thread. When asynchronous libraries are not available,
concurrent.futures.ThreadPoolExecutorcan be used to run any blocking code on another thread. This is a universal solution that can be used for any blocking function whether an asynchronous counterpart exists or not:
# `pip install futures` for python2
executor = concurrent.futures.ThreadPoolExecutor(8) class ThreadPoolHandler(RequestHandler): @gen.coroutine def get(self): for i in range(5): print(i) yield executor.submit(time.sleep, 1)
See the Asynchronous I/O chapter of the Tornado user’s guide for more on blocking and asynchronous functions.
My code is asynchronous, but it’s not running in parallel in two browser tabs.
Even when a handler is asynchronous and non-blocking, it can be surprisingly tricky to verify this. Browsers will recognize that you are trying to load the same page in two different tabs and delay the second request until the first has finished. To work around this and see that the server is in fact working in parallel, do one of two things:Add something to your urls to make them unique. Instead of
http://localhost:8888in both tabs, load
http://localhost:8888/?x=1in one and
http://localhost:8888/?x=2in the other.
Use two different browsers. For example, Firefox will be able to load a url even while that same url is being loaded in a Chrome tab.
相关文章推荐
- uefi怎么安装系统 UEFI+GTP模式安装Win7/Win8系统教程
- easyui-combo下拉框
- easyui north 穿透
- sqoop2增量导入无法指定last value问题解决方法
- ios开发UIView自适应问题
- easyui 动态生成datagrid列
- JS之模板技术(aui / artTemplate)
- 如何限制一个UITextField的输入长度
- easyui--validate验证
- UEFI的两种启动模式
- 在Legacy BIOS与UEFI 两种模式安装Windows 8操作系统的方法
- ZOJ 3911 Prime Query (线段树区间更新)
- Android中build target,minSdkVersion,targetSdkVersion,maxSdkVersion概念区分
- 设计模式之建造者模式(Builder)
- UITableView UICollectionView经验积累
- UEFI模式安装Win7旗舰版系统的方法
- UEFI模式安装win8,让开机速度快如闪电!
- Qt GUI程序中主线程与非主线程之间的通信
- Tips:取消UICollectionView的隐式动画
- UEFI安全启动怎么关闭 关闭UEFI启动项的方法图解