• 协程


    协程定义

    协程的概念早期是由生成器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里面的异步是怎么实现的...

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

  • 相关阅读:
    多种开源OLAP引擎测评报告
    Go的单元测试
    C#的List实现IComparer接口排序实例
    Java 多线程:(一)
    android:theme
    android:excludeFromRecents="true"
    RK:主屏幕
    Gatsby xinhua log boork(三)
    RK:Provision.apk、SettingsProvider的分析、使用
    Camera(一):查看Camera设备详细信息
  • 原文地址:https://www.cnblogs.com/zengmu/p/13090226.html
Copyright © 2020-2023  润新知