异步IO(协程,消息循环队列)
同步是CPU自己主动查看IO操作是否完成,异步是IO操作完成后发出信号通知CPU(CPU是被通知的)
阻塞与非阻塞的区别在于发起IO操作之后,CPU是等待IO操作完成再进行下一步操作,还是不等待去做其他的事直到IO操作完
成了再回来进行。
消息模型:当遇到IO操作时,代码只负责发出IO请求,不等待IO结果,然后直接结束本轮消息处理,进入下一轮
消息处理过程。当IO操作完成后,将收到一条“IO完成”的消息,处理该消息时就可以直接获取IO操作结果。
子程序调用总是一个入口,一次返回,调用顺序是明确的,而协程的调用和子程序不同(有多个入口,多次返回)。
#协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行
协程子程序切换不是线程切换(系统自动执行),而是有程序自身控制。
#Python对协程的支持是通过generator实现的。
#在generator中,我们不但可以通过for循环来迭代,还可以不断调用next()函数获取有yield语句返回的下一个值。
#但是Python的yield不但可以返回一个值,还可以接收调用者发出的参数。
def consumer():
r=''
while True:
n=yield r
if not n:
return
print('[CONSUMER]Consuming %s...' % n)
r='200 OK'
def produce(c):
c.send(None) #调用c.send(None)启动生成器,程序跳转到consumer,运行至yield 处结束返回produce.
n=0
while n<5:
n=n+1
print('[PRODUCER]Producing %s...' %n)
r=c.send(n) #通过c.send(n)切换到consumer执行
print('[PRODUCER]cONSUMER RETURN: %s' %r)
c.close()
c=consumer()
produce(c)
'''
1.首先调用c.send(None)启动生成器
2.然后,一旦产生了东西,通过c.send(n)切换到consumer执行
3.consumer通过yield拿到消息,处理,又通过yield把结果传回
4.produce拿到consumer处理的结果,继续生产下一条消息
5.produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”而非线程的抢占式多任务。
send()和yield相互为 发送和接收 参数 r=c.send(n),将参数n 传递给c函数,由c函数中的yield 及其后的变
量 接收,c中的程序再次运行到yield时,yield将其后的变量作为返回值,也就是c.send(n)的值
'''
'''
[PRODUCER]Producing 1...
[CONSUMER]Consuming 1...
[PRODUCER]cONSUMER RETURN: 200 OK
[PRODUCER]Producing 2...
[CONSUMER]Consuming 2...
[PRODUCER]cONSUMER RETURN: 200 OK
[PRODUCER]Producing 3...
[CONSUMER]Consuming 3...
[PRODUCER]cONSUMER RETURN: 200 OK
[PRODUCER]Producing 4...
[CONSUMER]Consuming 4...
[PRODUCER]cONSUMER RETURN: 200 OK
[PRODUCER]Producing 5...
[CONSUMER]Consuming 5...
[PRODUCER]cONSUMER RETURN: 200 OK
'''
#asyncio是Python3.4版本引入的标准库,直接内置了对异步IO的支持
#asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个Eventloop的引用,然后把需要执行的协程扔到Eventloop中执行,就实现了异步IO。
#用asyncio实现Hello world 代码如下:
'''
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' %threading.currentThread())
yield from asyncio.sleep(1)
print('Hello again!(%s)' % threading.currentThread())
loop=asyncio.get_event_loop()
tasks=[hello(),hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
'''
'''
Hello world! (<_MainThread(MainThread, started 5524)>)
Hello world! (<_MainThread(MainThread, started 5524)>)
(暂停约1秒)
Hello again!(<_MainThread(MainThread, started 5524)>)
Hello again!(<_MainThread(MainThread, started 5524)>)
'''
# @asyncio.coroutine把一个generator标记为corroutine类型,然后,我们就把这个coroutine扔到Eventloop
中执行。
#hello()会首先打印出Hello world!,然后,yield from 语法可以让我们方便地调用另一个generator.由于
asyncio.sleep()也是一个coroutine,所以线程不会等待
#asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from
拿到返回值(此处是None),然后接着执行下一行语句。
#把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行Eventloop中其他可以执
行的coroutine了,因此可以实现并发执行。
多个coroutine可以封装成一组task然后并发执行。
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个Eventloop的引用,然后把需要执行的协程扔
到Eventloop中执,就实现了异步IO。
为了简化并更好地标识异步IO,从Python3.5开始引入新的语法async和await,可以让coroutine的代码更简洁易读。
'''
1. 把@asyncio.coroutine替换为async;
2. 把yield from 替换为await
'''
#例
'''
@asyncio.coroutine
def hello():
print("hello world!")
r = yield from asyncio.sleep(1)
print("hello again!")
'''
#可写成
'''
async def hello():
print("hello world!")
r=await asyncio.sleep(1)
print("hello again!")
'''
#剩下的代码保持不变
#aiohttp
#asyncio可以实现单线程并发IO操作。如果仅用在客户端,发挥的威力不大。如果把asyncio用在服务器端,例如web服务器,由于http连接就是IO操作,因此可以用
#单线程+coroutine实现多用户的高并发支持。
#asyncio实现了TCP UDP SSL等协议,aiohttp则是基于asyncio实现的http框架。
#编写一个http服务器 ,分别处理一下URL:
'''
* / -首页返回b'<h1>Index</h1>';
* /hello/{name} -根据URL参数返回文本 hello,%s!.
'''
import asyncio
from aiohttp import web
async def index(request):
await asyncio.sleep(0.5)
return web.Response(body=b'<h1>Index</h1>',content_type='text/html')
async def hello(request):
await asyncio.sleep(0.5)
text='<h1>hello, %s!<h1>' %request.match_info['name']
return web.Response(body=text.encode('utf-8'),content_type='text/html')
async def init(loop):
app=web.Application(loop=loop)
app.router.add_route('GET','/',index)
app.router.add_route('GET','/hello/{name}',hello)
srv=await loop.create_server(app.make_handler(),'127.0.0.1',8000)
print('Server started at http://127.0.0.1:8000...')
return srv
loop=asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()
#aiohttp的初始化函数init()也是一个coroutine,loop.create_server()则利用asyncio创建TCP服务
异步IO(协程,消息循环队列)的更多相关文章
- 2020.11.2 异步IO 协程
异步IO 同步IO在一个线程中,CPU执行代码的速度极快,然而,一旦遇到IO操作,如读写文件.发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作. 在IO操作的过程中,当前线程被挂起,而其 ...
- python并发编程之多进程、多线程、异步、协程、通信队列Queue和池Pool的实现和应用
什么是多任务? 简单地说,就是操作系统可以同时运行多个任务.实现多任务有多种方式,线程.进程.协程. 并行和并发的区别? 并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任 ...
- 异步IO/协程/数据库/队列/缓存(转)
原文:Python之路,Day9 - 异步IO\数据库\队列\缓存 作者:金角大王Alex add by zhj: 文章很长 引子 到目前为止,我们已经学了网络并发编程的2个套路, 多进程,多线程,这 ...
- python -- 异步IO 协程
python 3.4 >>> import asyncio >>> from datetime import datetime >>> @asyn ...
- python异步加协程获取比特币市场信息
目标 选取几个比特币交易量大的几个交易平台,查看对应的API,获取该市场下货币对的ticker和depth信息.我们从网站上选取4个交易平台:bitfinex.okex.binance.gdax.对应 ...
- Python自动化运维之16、线程、进程、协程、queue队列
一.线程 1.什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行 ...
- Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)
Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...
- Tornado异步之-协程与回调
回调处理异步请求 回调 callback 处理异步官方例子 # 导入所需库 from tornado.httpclient import AsyncHTTPClient def asynchronou ...
- python并发编程之多进程、多线程、异步和协程
一.多线程 多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活状态,从而让多个函数的操作同时运行.即使是单CPU的计算机,也可以通过不停地在不同线程的指令间切换,从而造成多线程同时运行 ...
随机推荐
- linux中tar命令(打包、压缩、解压)、zip和unzip、rar多种压缩文件
一.名词解释 打包:将一大堆文件或目录变成一个总的文件[tar命令] 压缩:将一个大的文件通过一些压缩算法变成一个小文件[gzip,bzip2等] Linux中很多压缩程序只能针对一个文件进行压缩,这 ...
- boke例子:用户登录
boke例子:用户登录 1.首先创建user表,authority表(角色),user_authority,表(用户角色表) Authority实体类,需要继承:GrantedAuthority类, ...
- c# 正则表达式如何处理换行符?
我们要分析网页,把整个网页内容作为匹配源,但是c#的正则表达式是默认以一行为单位的,使用 RegexOptions.Multiline 也没有实质性作用(它知识改变了^和$的行为) 只要在正则表达式前 ...
- uva10780
将m分解质因数,然后计算次数取最小. #include <iostream> #include <cstdio> #include <cmath> #include ...
- vi常用快捷键
vi常用快捷键 1)移动光标 h :光标左移一个字符k :光标上移一个字符j :光标下移一个字符l :光标右移一个字符 0 :光标移至行首$ :光标移至行尾 H :光标移至屏幕首行M :光标移至屏幕中 ...
- ubuntu下安装CAJ阅读器
目录 1.ubuntu下wine的基本介绍 (1)wine的介绍 (2)wine的安装 (3)exe文件的安装 (4)exe程序的卸载 (6)wine的基本使用 2.CAJ阅读器的安装 (1)首先放上 ...
- React文档(二)Hello World
开始学习React最简单的实践就是去试一试CodePen上面的Hello World程序.你不需要安装任何东西,只要新开一个标签页打开例子依照原例操作即可.如果你更喜欢在本地开发,那么来看看安装的介绍 ...
- python low版线程池
1.low版线程池设计思路:运用队列queue 将线程类名放入队列中,执行一个就拿一个出来import queueimport threading class ThreadPool(object): ...
- commonJS,常用js工具方法
说明:平时项目用到的一些常见过滤方法,有些是vue过滤器,稍微修改下吧,我就不改了. js四舍五入不准确的解决(重写方法): Number.prototype.toFixed = function(l ...
- ajax请求成功前,加载中loading显示
/*第一次刷新--非定时器刷新数据*/ var fistInitColumn = true; var getAllColumnDatas = function(){ var params = {}; ...