协程

协程定义

协程的概念早期是由生成器yield -->yield from-->coroutine 演变而来的,熟悉yield关键字都知道一个重要的性质:会从程序上次中断的地方继续往下执行-->有自己的上下文寄存器和栈,不被内核控制,由开发者决定什么时候让出执行权。 现在有很多概念说是一种轻量级的线程(可能大概是因为协程在线程程中被创建)...
个人理解:协程是一种用户态线程,切换不由内核而由用户自定义的线程.


为什么有协程

比较一下协程相对线程的优势|

种类 线程 协程
上下文切换开销
并发能力
资源同步考虑 考虑 不考虑

协程概念组成

  1. 事件循环:所有的协程对象会被注册到该循环中
                  loop = asyncio.get_event_loop()
  2. 协程对象:常见IO操作封装在协程对象中,由关键字async 定义
                  async def request():

                         url = 'http://127.0.0.1:5000'
                         print('Waiting for', url)
                         result = await get(url)
                         print('Get response from', url, 'Result:', result)
  3.任务(期物):对协程对象的进一步封装,比如会赋予协程状态
                  task = asyncio.ensure_future(request())
  4.await关键字 (区别于asyncio.wait(fps,timeout=)):前者是关键字。后者解决事件循环中某一协程阻塞时间过程的问题

协程的简单使用例子

from flask import Flask
import time

app = Flask(__name__)


@app.route('/')
def index():

    time.sleep(3)
    return 'hello'


if __name__ == '__main__':

    app.run(host='127.0.0.1', port=5000, threaded=True)

使用流程 创建task(s),创建事件循环,将任务提交到事件循环中去:

    # tasks = [asyncio.ensure_future(get_files(i)) for i in range(6)]
    #创建任务列表(里面包含协程对象)  但是这并不是一个协程对象
    tasks = [asyncio.ensure_future(request()) for _ in range(4)]       
    #开启事件循环
    loop = asyncio.get_event_loop()
    #将任务列表添加到事件里面(若是协程对象 直接传协程对象)
    loop.run_until_complete(asyncio.wait(tasks))
    # p = ThreadPoolExecutor(max_workers=120)
    # for _ in range(100):
    #     p.submit(tes)
    # p.shutdown(wait=True)
    end = time.time()
    print('Cost time:', end - start)

![]

这样的一个程序确实 是起到了协程的作用,遇到await关键字,将程序挂起,执行权让给其他协程,问题是在于请求网络阻塞的时间太长,而使得我们希望的高并发能力表现不出来,最终导致的是
13s的时间,在理论上如果我们能够将请求网络这个操作挂起的话,就真正的能够实现我们所希望的并发能力,但是实际是 请求网络返回的Response类并没有实现__await__方法,所以只能生生阻塞成线性时间


而这个时候 解决问题的库 aiohttp 就出来了,异步库:解决问题的核心是什么呢? ---->背后往往都会借助于IO的事件循环B来实现异步,我们请求网络遭遇阻塞时,将该套接字放入另外一个事件循环B里面,一直维持连接监听,而在主线程的事件循环A中 继续执行其他协程,当另外一个IO事件循环B里面的监听状态发生改变,会唤醒当前的事件循环A中的协程,进行我们需要的处理,这样!我们所期望的并发能力就出现了

我也有用concurrent.future 里面的线程池 实现过100个线程异步提交和100个协程的比较 结果 前者是3.5S后者还是2.1左右 是真的猛啊!

协程进一步了解

0.协程的前世 yield 和 yield from是怎么实现原生协程的
1.如何动态得往事件中添加任务
2.如何查看事件循环中的各任务状态
3.如何开启一个新的事件循环
4.协程相关的异步库
5.tornado里面的异步是怎么实现的...

有错请指出哈........................

原文地址:https://www.cnblogs.com/zengmu/p/13090226.html