• 协程


    1.携程的概念

    # 进程 资源分配的最小单位
    # 线程 CPU执行的最小单位

    # 只要是线程里的代码 就都被CPU执行就行
    # 线程是由 操作系统 调度,由操作系统负责切换的
    # 协程:
       # 用户级别的,由我们自己写的python代码来控制切换的
       # 是操作系统不可见的
    # 在Cpython解释器下 - 协程和线程都不能利用多核,都是在一个CPU上轮流执行
       # 由于多线程本身就不能利用多核
       # 所以即便是开启了多个线程也只能轮流在一个CPU上执行
       # 协程如果把所有任务的IO操作都规避掉,只剩下需要使用CPU的操作
       # 就意味着协程就可以做到提高CPU利用率的效果
    # 多线程和协程
       # 线程 切换需要操作系统,开销大,操作系统不可控,给操作系统的压力大
           # 操作系统对IO操作的感知更加灵敏
       # 协程 切换需要python代码,开销小,用户操作可控,完全不会增加操作系统的压力
           # 用户级别能够对IO操作的感知比较低

    2.切换问题

    # 协程 :能够在一个线程下的多个任务之间来回切换,那么每一个任务都是一个协程
    # 两种切换方式
       # 原生python完成   yield asyncio
       # C语言完成的python模块 greenlet gevent

    greenlet
    import time
    from  greenlet import greenlet

    def eat():
       print('wusir is eating')
       time.sleep(0.5)
       g2.switch()
       print('wusir finished eat')

    def sleep():
       print('小马哥 is sleeping')
       time.sleep(0.5)
       print('小马哥 finished sleep')
       g1.switch()

    g1 = greenlet(eat)
    g2 = greenlet(sleep)
    g1.switch()

    3.gevent模块

    import time
    print('-->',time.sleep)
    import gevent
    from gevent import monkey
    monkey.patch_all()
    def eat():
       print('wusir is eating')
       print('in eat: ',time.sleep)
       time.sleep(1)
       print('wusir finished eat')

    def sleep():
       print('小马哥 is sleeping')
       time.sleep(1)
       print('小马哥 finished sleep')

    g1 = gevent.spawn(eat)  # 创造一个协程任务
    g2 = gevent.spawn(sleep)  # 创造一个协程任务
    g1.join()   # 阻塞 直到g1任务完成为止
    g2.join()   # 阻塞 直到g1任务完成为止


    import time
    import gevent
    from gevent import monkey
    monkey.patch_all()
    def eat():
       print('wusir is eating')
       time.sleep(1)
       print('wusir finished eat')

    def sleep():
       print('小马哥 is sleeping')
       time.sleep(1)
       print('小马哥 finished sleep')

    # g1 = gevent.spawn(eat) # 创造一个协程任务
    # g3 = gevent.spawn(eat) # 创造一个协程任务
    # g2 = gevent.spawn(sleep) # 创造一个协程任务
    # # g1.join()   # 阻塞 直到g1任务完成为止
    # # g2.join()   # 阻塞 直到g1任务完成为止
    # gevent.joinall([g1,g2,g3])
    g_l = []
    for i in range(10):
       g = gevent.spawn(eat)
       g_l.append(g)
    gevent.joinall(g_l)

    import time
    import gevent
    from gevent import monkey
    monkey.patch_all()
    def eat():
       print('wusir is eating')
       time.sleep(1)
       print('wusir finished eat')
       return 'wusir***'

    def sleep():
       print('小马哥 is sleeping')
       time.sleep(1)
       print('小马哥 finished sleep')
       return '小马哥666'

    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(sleep)
    gevent.joinall([g1,g2])
    print(g1.value)
    print(g2.value)

    4.asyncio模块

    ```python
    import asyncio

    # 起一个任务
    async def demo(): # 协程方法
    print('start')
    await asyncio.sleep(1) # 阻塞
    print('end')

    loop = asyncio.get_event_loop() # 创建一个事件循环
    loop.run_until_complete(demo()) # 把demo任务丢到事件循环中去执行

    # 启动多个任务,并且没有返回值
    async def demo(): # 协程方法
    print('start')
    await asyncio.sleep(1) # 阻塞
    print('end')

    loop = asyncio.get_event_loop() # 创建一个事件循环
    wait_obj = asyncio.wait([demo(),demo(),demo()])
    loop.run_until_complete(wait_obj)

    # 启动多个任务并且有返回值
    async def demo(): # 协程方法
    print('start')
    await asyncio.sleep(1) # 阻塞
    print('end')
    return 123

    loop = asyncio.get_event_loop()
    t1 = loop.create_task(demo())
    t2 = loop.create_task(demo())
    tasks = [t1,t2]
    wait_obj = asyncio.wait([t1,t2])
    loop.run_until_complete(wait_obj)
    for t in tasks:
    print(t.result())

    # 谁先回来先取谁的结果
    import asyncio
    async def demo(i): # 协程方法
    print('start')
    await asyncio.sleep(10-i) # 阻塞
    print('end')
    return i,123

    async def main():
    task_l = []
    for i in range(10):
    task = asyncio.ensure_future(demo(i))
    task_l.append(task)
    for ret in asyncio.as_completed(task_l):
    res = await ret
    print(res)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

    import asyncio

    async def get_url():
    reader,writer = await asyncio.open_connection('www.baidu.com',80)
    writer.write(b'GET / HTTP/1.1 HOST:www.baidu.com Connection:close ')
    all_lines = []
    async for line in reader:
    data = line.decode()
    all_lines.append(data)
    html = ' '.join(all_lines)
    return html

    async def main():
    tasks = []
    for url in range(20):
    tasks.append(asyncio.ensure_future(get_url()))
    for res in asyncio.as_completed(tasks):
    result = await res
    print(result)


    if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main()) # 处理一个任务


    # python原生的底层的协程模块
    # 爬虫 webserver框架
    # 题高网络编程的效率和并发效果
    # 语法
    # await 阻塞 协程函数这里要切换出去,还能保证一会儿再切回来
    # await 必须写在async函数里,async函数是协程函数
    # loop 事件循环
    # 所有的协程的执行 调度 都离不开这个loop
    ```

  • 相关阅读:
    SpringMVC 拦截器
    Download And Uploader
    Spring 作用域传值
    Spring MVC 视图解析 VIEW
    SpringMVC自动注入
    cmake编译opencv4项目遇到opencv_found set to false问题
    vscode配置c++开发环境
    CMakeLists.txt样本
    mysql5.7高版本加载低版本sql文件,时间不能为0000-00-00格式错误
    log4j.properties配置
  • 原文地址:https://www.cnblogs.com/usherwang/p/13054206.html
Copyright © 2020-2023  润新知