tornado学习笔记day07-同步与异步

同步

概念

同步就是按部就班的依次执行我们的代码

进阶

但是有些情况我们有一些比较耗时的从操作,比如去别的地方拿点资源,去其他网站请求数据,去访问数据库,上传文件等等,所以这里面优点瑕疵,有小编一一道来
比如这样

''' 本模块的功能:<同步异步demo>'''# 这个就相等于一个客户端的请求
import time# 添加一个耗时的操作
def longIO():print("开始耗时操作")time.sleep(5)print("结束耗时操作")def reqA():print("开始处理reqA")longIO()print("结束处理reqA")# 这个就相等于另一个客户端的请求
def reqB():print("开始处理reqB")print("结束处理reqB")
def main():# 这就是同步在处理reqA()reqB()while True:'''# 如果你要想写死循环,你不要直接写死循环,你得睡一睡# 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%'''time.sleep(0.1)
if __name__ == '__main__':main()

结果

开始处理reqA
开始耗时操作# 这里等待了5秒钟
结束耗时操作
结束处理reqA
开始处理reqB
结束处理reqB

在请求中添加了一个耗时的操作,导致了我们的同步的效率特别低了,这样也体现不出我们tornado高效的优点

'''┌─┐       ┌─┐ + +┌──┘ ┴───────┘ ┴──┐++│                 ││       ───       │++ + + +███████───███████ │+│                 │+│       ─┴─       ││                 │└───┐         ┌───┘│         ││         │   + +│         ││         └──────────────┐│                        ││                        ├─┐│                        ┌─┘│                        │└─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +│ ─┤ ─┤       │ ─┤ ─┤└──┴──┘       └──┴──┘  + + + +神兽保佑代码无BUG!'''

异步

你干一件事情的同事又去干另一件事情

概述

对于耗时的操作,会交给别人(另一个线程)处理,我们继续向下执行,当别人结束耗时操作后,再将处理结果返回给我们

回调函数实现异步

异步其实我们已经用了,js里面有一个很明显的异步,就是在我们发ajax的时候,当我们发完ajax就去干别的活去了,后来ajax有响应了我们才搭理他

来来来,代码演示如下:

'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模块的功能:<异步演示demo># 这个就相等于一个客户端的请求
import time
import threading
''' 添加一个耗时的操作''''''
这样就会有一个问题,这个run()函数的返回值我们接受不到
为了解决这个问题,我们需要写一个函数,这个函数叫做回调函数
'''
def longIO(callback):def run(cb):print("开始耗时操作")time.sleep(3)print("结束耗时操作")cb("victor is a wonderful man")threading.Thread(target=run,args=(callback,)).start()

这个longio这部分 ,就像ajax一样都不用我们来写了

def finish(data):print("开始处理回调函数")print("接受到longIO的数据为:",data)print("结束处理回调函数")def reqA():print("开始处理reqA")longIO(finish)print("结束处理reqA")# 这个就相等于另一个客户端的请求
def reqB():print("开始处理reqB")time.sleep(1)print("结束处理reqB")
def main():# 这就是同步在处理reqA()reqB()while True:'''# 如果你要想写死循环,你不要直接写死循环,你得睡一睡# 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()

异步只是说tornado能处理多个请求了,你浏览器该等还是得等着

协程实现异步

协程还不理解呢,还想实现异步,你就实现就行了

不用管拥护啥了,进程线程你们搞起来都麻烦呢,更别说协程了

版本1

最low的一个初级版本

'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模块的功能:<># 这个就相等于一个客户端的请求
import time
import threadinggen = None# 添加一个耗时的操作
def longIO():def run():print("开始耗时操作")time.sleep(3)try:global gengen.send("victor is wonderful!!!")except StopIteration as e:passprint("结束耗时操作")threading.Thread(target=run,).start()
# 这个longio这部分 ,就像ajax一样都不用我们来写了
'''
这样就会有一个问题,这个run()函数的返回值我们接受不到
为了解决这个问题,我们需要写一个函数,这个函数叫做回调函数
'''def reqA():print("开始处理reqA")res = yield longIO()print("接受到longIO的数据为:",res)# 这里就相当于挂起了print("结束处理reqA")# 这个就相等于另一个客户端的请求
def reqB():print("开始处理reqB")time.sleep(1)print("结束处理reqB")def main():# 这就是同步在处理global gengen = reqA()    # 生成一个生成器next(gen)   # 执行reqAreqB()while True:'''# 如果你要想写死循环,你不要直接写死循环,你得睡一睡# 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()
版本2
我们有一个问题

版本1中在调用reqA的时候和reqB的调用方式可不一样的啊
也就数不能将其视为简单的函数,而是需要作为生成器来用,我们想的时候是当成一个普通函数来对待

现实
global gen
gen = reqA()    # 生成一个生成器
next(gen)   # 执行reqA
理想
reqA()   # 仅仅的简单的调用

这个时候寄需要我们的装饰器来登场了

''' 装饰器还会写么'''
def genCoroutine(func):# 这个是带有参数的装饰器def wapper(*args,**kwargs):# 其实说白了还是那三句话global gengen = func(*args,**kwargs)  # 生成一个生成器next(gen)  # 执行reqAreturn wapper 

然后定义的时候

@genCoroutine
def reqA():print("开始处理reqA")res = yield longIO()print("接受到longIO的数据为:",res)# 这里就相当于挂起了print("结束处理reqA")

然后执行的时候

'''这个就相等于另一个客户端的请求 '''
def reqB():print("开始处理reqB")time.sleep(1)print("结束处理reqB")def main():# 这就是同步在处理# global gen# gen = reqA()    # 生成一个生成器# next(gen)   # 执行reqAreqA()reqB()while True:'''# 如果你要想写死循环,你不要直接写死循环,你得睡一睡# 为什么要睡一睡呢,因为你要是不睡你会发现你的CPU利用率占100%'''time.sleep(0.1)if __name__ == '__main__':main()
版本3

其实版本2中还有一个问题,他存在一个全局的gen变量,说白了就是假装让他不再那块儿

这个是最复杂版本,看看吧

  1. 文档说明,导入相关模块
'''
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Created by victor
'''
# 本模块的功能:<>import time
import threading
  1. 定义装饰器(最重要的部分,实现异步,高效,并发的原理)
def genCoroutine(func):'''这个好多人就屡不清了'''def wapper(*args, **kwargs):'''这样的话这个装饰器就麻烦了,因为我还得要这个全局的gen啊我需要获得多个生成器'''gen1 = func()  # reqA的生成器gen2 = next(gen1)  # longIO的生成器# 在这里面创建我的线程# 挂起他def run(g):# 这个就是执行longIO去了res = next(g)try:gen1.send(res)  # 返回给reqA数据except StopIteration as e:# 啥都不干passthreading.Thread(target=run, args=(gen2,)).start()return wapper
  1. 最难执行的部分
'''
# 添加一个耗时的操作
# handler获取数据,(数据库,其他服务器,循环耗时)
'''
def longIO():'''现在你只需要知道你的耗时的操作是啥,线程的东西你不用管了tornado都帮你弄好了'''print("开始耗时操作")time.sleep(3)print("结束耗时操作")# 结束耗时操作后的返回数据yield "victor is a cool man"
  1. 被装饰函数定义
@genCoroutine
def reqA():print("开始处理reqA")res = yield longIO()print("接受到longIO的数据为:", res)# 这里就相当于挂起了print("结束处理reqA")
  1. 另一个耗时函数
''' 这个就相等于另一个客户端的请求'''
def reqB():print("开始处理reqB")time.sleep(1)print("结束处理reqB")
  1. 程序入口函数
def main():reqA()reqB()while True:time.sleep(0.1)if __name__ == '__main__':main()

以后我们不用谢这么复杂的装饰器了,tornado已经帮我们写好了,你只要有异步就用装饰器来装饰一下就OK,其他的都不需要写

tornado里面指正不是这么写代码,不然要是这样写,你们全费了,tornado留下的都是简单易用的

这玩意不是你理解不理解,你一开始指定是不理解,你多用才能懂里面的原理

这个协程中的异步,其实他本质上不是协程,以为他用了多个线程,因为协程的定义是在一个线程里面玩的,只是来理解tornado实现原理

相似文章

tornado学习笔记day01
tornado学习笔记day02
tornado学习笔记day03
tornado学习笔记day04
tornado学习笔记day05
tornado学习笔记day06
tornado学习笔记day07
tornado学习笔记day08

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关键字: on

关键字: on 数据库在通过连接两张或多张表来返回记录时&#xff0c;都会生成一张中间的临时表&#xff0c;然后再将这张临时表返回给用户。 在使用left jion时&#xff0c;on和where条件的区别如下&#xff1a; 1、 on条件是在生成临时表时使用的条件&#xff0c;它不管on中的条…

天融信安全接入客户端_天融信提示您警惕物联网设备Ripple20漏洞风险

近日&#xff0c;天融信阿尔法实验室在JSOF实验室发布的由Treck公司开发的TCP/IP软件库中获取到一系列0day漏洞。JSOF实验室发布的这批漏洞共计19个&#xff0c;被JSOF研究人员称为"Ripple20"。受此软件库影响的产品数量估计超过数亿&#xff0c;其中包括智能家居设备…

Service-Oriented Architecture,SOA(转)

http://blog.csdn.net/WOOSHN/article/details/8036910 介绍&#xff1a; IT体系结构已非常成熟&#xff0c;它是一种成功处理典型IT问题的方法。体系结构中一个受到很大重视且相对较新的分支是面向服务的体系结构(SOA)。SOA经常被吹捧为企业用于解决应用程序灵活性和高维护成本…

tornado学习笔记day08-tornado中的异步

概述 应为epoll主要用来解决网络的并发问题,所以tornado中的异步也是主要体现在网络的IO异步上,即异步web请求 tornado.httpclient.AsyncHTTPClient tornado提供异步web请求客户端,可以用来进行异步web请求, 这个客户端和服务端是相对来说的,当tornado的Handler去其他位置去…

GreenSock (TweenMax) 动画案例(二)

实现效果 动画分解 1.灯光闪烁2.文字出现3.水流4.心电图 知识点 1.AI(可尽情骚扰UI欧巴)2.SVG(了解基本的知识点)3.TweenMax(GreenSock)4.CSS animation 写在前面 写过第一篇文章后GreenSock (TweenMax) 动画案例(一)再回头看发现代码太多&#xff0c;根本没耐心去看完。所以每…

vue 用key拿对象value_利用 WeakMap 对 Vue 新建数组中的对象赋予 :key

需求在 Vue 中&#xff0c;对组件进行循环都需要加入key以便“就地复用”&#xff0c;可是在某些情况下&#xff0c;我们需要新建多个对象&#xff0c;而这些对象不是从后端获取到的&#xff0c;而是前端生成的&#xff0c;没有唯一值&#xff0c;且 Vue 目前版本只允许字符串&…

无限轮播图片的实现原理

无限轮播图相信是很多开发人员常用的一个功能&#xff0c;这里总结一下常用的两种方式的实现原理 一、使用UIScrollview实现无限轮播用UIScrollView实现&#xff0c;在scrollView上添加3个UIImageView&#xff0c;分别用来显示上一张图片&#xff0c;当前显示的图片&#xff0c…

开启 JM 的 trace 功能

[JM代码] 开启 JM 的 trace 功能本帖最后由 firstime 于 2009-6-15 11:16 AM 编辑 城里汉子说过&#xff1a; trace文件对分析码流结构很有效。我说的是trace文件&#xff0c;不是一步一步跟踪&#xff0c;就是编解码同时生成的 trace_enc.txt 这个文件&#xff0c;里面对每个比…

kafka入门介绍(转载)

Kafka作为一个分布式的流平台&#xff0c;这到底意味着什么&#xff1f; 我们认为&#xff0c;一个流处理平台具有三个关键能力&#xff1a; 发布和订阅消息&#xff08;流&#xff09;&#xff0c;在这方面&#xff0c;它类似于一个消息队列或企业消息系统。 以容错的方式存储…

Cmd Markdown 编辑阅读器

欢迎使用 Cmd Markdown 编辑阅读器 我们理解您需要更便捷更高效的工具记录思想&#xff0c;整理笔记、知识&#xff0c;并将其中承载的价值传播给他人&#xff0c;Cmd Markdown 是我们给出的答案 —— 我们为记录思想和分享知识提供更专业的工具。 您可以使用 Cmd Markdown&…

关于在smarty中实现省市区三级联动

刚开始接触php&#xff0c;&#xff0c;其实对于一些比较深入的东西还不是很了解&#xff0c;就像是这次的省市区联动&#xff0c;都是用三张表为基础编码的&#xff0c;原谅我的无知&#xff0c;谢谢。 接下来就是编码部分了&#xff1a; <?php require(./smarty/Smarty.c…

Ubuntu GitLab CI Docker ASP.NET Core 2.0 自动化发布和部署(1)

相关博文&#xff1a; Ubuntu 简单安装和配置 GitLabUbuntu 简单安装 DockerUbuntu Docker 简单安装 GitLabUbuntu Docker 安装和配置 GitLab CI 持续集成服务器版本 Ubuntu 16.04 LTS。 经过上面四篇博文中的相关安装和配置&#xff0c;我们主要完成了两个容器的创建和运行&am…

X264学习笔记(1)

X264学习笔记&#xff08;1&#xff09; X264编码流程 参数的初始化 1.opt&#xff0c;param根据输入的参数和标准的规定&#xff0c;进行初始化设置。 Opt的说明如下&#xff1a; Opt->hin用于给出读入的yuv文件的指针地址 Opt->hout给出了输出的文件的指针地址 Opt->…

python 数字转化excel行列_Python实现excel的列名称转数字、26进制(A-Z)与10进制互相转换...

Python实现excel的列名称转数字、26进制(A-Z)与10进制互相转换sequence list( map( lambda x: chr( x ), range( ord( A ), ord( Z ) 1 ) ) )##-----字母转数字(python实现 1-26A-Z, then AA-AZ)def ten2TwentySix(num):L []numnum-1; #实现从1对应Aif num > 25:while Tr…

错误提示:'……' is not assignable to Android.app.Activity Manifest XML

1 问题描述&#xff1a; 针对这段代码&#xff1a; <activity android:name".fragament.fragment_bulter" /> <activity android:name".fragament.fragment_girl" /> <activity android:name".fragament.fragment_user" />…

关于Lambda和匿名内部类

先上代码&#xff1a; //gcache(f)public <T,R> Function<T,R> cache(Function<T,R> f){final Map<T,R> cachenew HashMap<>();Function<T,R> gt->{if(cache.containsKey(t)){System.out.println("cached t:"t);return cache…

H26L encoder.cfg参数分析

H264 encoder.cfg参数分析 收藏 (1) 文件操作参数:#Files InputFile "silent.yuv" #输入序列,YUV 4:2:0 StartFrame 0 # 从视频流的第几帧开始编码 FramesToBeEncoded 30 #编码图象帧数,指明了除去 B帧后将要被编码的帧数(应该再实验一下&#x…

django-ckeditor表情包修改

一、版本 Django1.11django-ckeditor5.2.2 二、关键步骤 1.删除旧的ckeditor静态文件 所在目录&#xff1a;项目目录下的static文件夹下的ckditor文件夹 rm ckeditor -rf 原因&#xff1a;在安装ckeditor后需要执行collectstatic命令&#xff0c;这个过程中的查找静态文件会去…

python中最难的是什么_python什么的最难了

学的人很少的,如果你没有学过编程,建议学c语言.因为python中文资料很少的.你可以先了解一下phthonpython的历史python的创始人为guido van rossum。1989年圣诞节期间&#xff0c;在阿姆斯特丹&#xff0c;guido为了打发圣诞节的无趣&#xff0c;决心开发一个新的脚本解释程序&a…

Python3生成脚本实现重置键盘键位

个人博客点这里 #!/usr/bin/env python # -*- coding:utf-8 -*- # Created by 秋叶夏风# 本模块的功能:<重置键盘键位>import sys import ossave_format "bat" # 这个值可以修改&#xff0c;有两个选项(bat和reg)&#xff0c;可选择生成bat批处理文件或者re…