• 二十、协程


    协程的概念
      线程:系统级别的
      协程:程序根据自己的需求调度。在同一个线程内一段代码在执行过程中会中断然后跳转执行别的代码,接着在之前中断的地方继续开始执行。携程拥有自己的寄存器上下文和栈。
    协程的优点
    1.无需线程上下文切换的开销,协程避免了无意义的调度,性能提高,程序员自己承担调用的责任。
    2.无需原子操作及同步开销
    3.方便切换,简化编程模式
    4.高并发+高扩展+低成本,一个cpu支持上万协程
    协程的缺点
    1.无法利用多核资源,协程本质是单线程,但可以和进程进行多核CPU,一般没需求
    2.进行阻塞操作,阻塞整个程序


    yield的使用
         Python对协程的支持是通过generator实现的。

    '''
    yield的使用
    '''
    #函数中存在yield表示是一个生成器generator
    def foo():
    while True:
    print('starting...')
    str=yield 4 #将yield看成是一个return返回语句
    print(str)

    f=foo()
    print(next(f)) #遍历生成器generator的下一个值
    print('*'*20)
    print(next(f))
    send发送数据
    
    
    send会接着上次中断的地方(return)开始执行,将发送的数据后,执行下一个next的作用,遇到下一个yield,返回结果结束。
    
    
    '''
    send方法发送数据 ,实现生产者消费着模式
    '''
    def producter(c):
    for i in range(1,10):
    print('生产者生产产品:%d'%i)
    c.send(i)
    def cunsumer():
    while True:
    num=yield
    print('消费者消费产品%d'%num)
    c=cunsumer()
    next(c)
    producter(c)
    协程的使用
      使用异步IO(asyncio)协程,提高我们我们软件系统的并发。
      并发的方式有多种,多线程、多进程、异步IO等,多线程核多进程之间的场景切换核通讯代价高,不适合IO密集型的场景,而异步IO适合密集型,将一个任务都耗费在CPu上。
      IO就是读写磁盘和网络,比读写CPU和内存慢的多。则密集型场景,99%以上都浪费在等待上,但异步IO就是将CPU从漫长的等待中解放出来。
    
    
     asyncio的编程模式就是一个消息循环,我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要的执行的协程仍到EventLoop中执行,实现异步IO。
    
    
    (1)event_loop事件循环:程序开启一个无限循环,程序员会把一些函数注册到使劲按循环上,当满足事件发生的时候,调用相应的协程函数
    
    
    (2)coroutine协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行,而是返回一个协程对象,协程对象需要注册到事件循环中,由事件循环进行执行。
    
    
    (3)task任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,包括任务的各种状态,比如挂起,执行等,获取协程的结果。
    
    
    (4)future:和tast没有区别,代表将要执行或没有执行的结果,是task的父类
    
    
    (5)async/await关键字:定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口
    
    
    '''
    定义一个协程
    '''
    import asyncio,time
    now=lambda: time.time()
    #使用async修饰一个函数,则该函数是一个协程对象
    async def foo(x):
    print('waiting:',x)
    #记录开始时间
    start =now()
    #创建事件循环
    loop=asyncio.get_event_loop()
    #将协程添加到事件循环中
    loop.run_until_complete(foo(3))
    print(now()-start)
    '''
    创建一个task任务
    '''
    import asyncio
    #使用async修饰一个函数,则该函数是一个协程对象
    async def foo(num):
    print('tasking',num)
    return 1
    #创造回调函数
    def collback(Future):
    print(Future.result())
    #创建事件循环
    loop=asyncio.get_event_loop()
    # 创建任务task
    task=loop.create_task(foo(3))
    print(task)#状态为pending
    print('如果task是Future的子类,则返回Ture:',isinstance(task,asyncio.Future))
    #task.add_done_callback(collback)添加回调函数
    #将任务添加到事件循环对象
    loop.run_until_complete(task)
    print(task.result())#获得协程对象的返回值
    print(task) #状态为finished
    
    
    '''
    模拟异步IO,await
    '''
    import asyncio,time
    #使用async修饰一个函数,则该函数是一个协程对象
    async def foo(num):
    print('tasking',num)
    await asyncio.sleep(num)
    return 1
    start=time.time()
    #创建事件循环
    loop=asyncio.get_event_loop()
    # 创建任务task
    task=asyncio.ensure_future(foo(3))
    loop.run_until_complete(task)
    print(task.result())#获得协程对象的返回值
    print(time.time()-start)

    '''
    可以将多个任务并行执行,但就是一个协程,因此多个任务,
    返回结果是同时返回的,比如1,4,9秒,最后结果是9秒后一起返回
    '''
    import asyncio,time
    #定义一个协程对象
    async def foo(x):
    print('Staring...',x)
    await asyncio.sleep(x)
    return x
    start=time.time()
    #创建协程对象
    object_1=foo(1)
    object_2=foo(5)
    object_3=foo(9)
    #创建任务
    tasks=[
    asyncio.ensure_future(object_1),
    asyncio.ensure_future(object_2),
    asyncio.ensure_future(object_3)
    ]
    #创建循环事件,循环执行
    loop=asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    #获取返回的值
    for task in tasks:
    print(task.result())
    print(time.time()-start)

    多种方式进行协程的嵌套

    '''
    五种协程嵌套方式
    '''
    import asyncio,time
    #定义一个协程对象
    async def foo(x):
    print('Staring...',x)
    await asyncio.sleep(x)
    return x
    async def main():
    # 创建协程对象
    object_1 = foo(1)
    object_2 = foo(5)
    object_3 = foo(9)
    # 创建任务
    tasks = [
    asyncio.ensure_future(object_1),
    asyncio.ensure_future(object_2),
    asyncio.ensure_future(object_3)
    ]
    #第一种方式
    # done,pending=await asyncio.wait(tasks)
    # for task in done:
    # print('tasks返回结果',task.result())
    #第二种方式
    # results=await asyncio.gather(*tasks)#tasks可变参数传入,一个个传入,接收也是列表接收
    # print(results)
    # for result in results:
    # print('result返回结果',result)
    #第三种方式
    # return await asyncio.wait(tasks)
    #第四种方式
    # return await asyncio.gather(*tasks)
    #第五种方式
    # for task in asyncio.as_completed(tasks):
    # result=await task
    # print('result返回结果', result)
    start=time.time()
    #创建循环事件,循环执行
    loop=asyncio.get_event_loop()
    #第一二五种方式
    #loop.run_until_complete(main())
    #第三种方式
    # done,pending=loop.run_until_complete(main())
    # for task in done:
    # print('task的值',task.result())
    #第四种方式
    # results=loop.run_until_complete(main())
    # for result in results:
    # print('result的结果:',result)
    print(time.time()-start)
    '''
    协程的停止模拟
    '''
    import asyncio,time
    #定义一个协程对象
    async def foo(x):
    print('Staring...',x)
    await asyncio.sleep(x)
    return x
    async def main():

    # 创建协程对象
    object_1 = foo(1)
    object_2 = foo(5)
    object_3 = foo(9)
    # 创建任务
    tasks = [
    asyncio.ensure_future(object_1),
    asyncio.ensure_future(object_2),
    asyncio.ensure_future(object_3)
    ]
    results=await asyncio.gather(*tasks)
    for result in results:
    print('结果:',result)
    #创建循环事件,循环执行
    loop=asyncio.get_event_loop()
    start=time.time()
    try:
    loop.run_until_complete(main())
    print(time.time() - start)
    except KeyboardInterrupt as e:
    #asyncio.Task.all_tasks()获取事件循环中的所有任务列表
    print(asyncio.gather(*asyncio.Task.all_tasks()).cancel())
    loop.stop()
    loop.run_forever()

    finally:
    loop.close()
  • 相关阅读:
    [LeetCode] 1268. Search Suggestions System
    [LeetCode] 907. Sum of Subarray Minimums
    [LeetCode] 2034. Stock Price Fluctuation
    [LeetCode] 792. Number of Matching Subsequences
    [LeetCode] 212. Word Search II
    [LeetCode] 828. Count Unique Characters of All Substrings of a Given String
    [LeetCode] 408. Valid Word Abbreviation
    [LeetCode] 1161. Maximum Level Sum of a Binary Tree
    [LeetCode] 1152. Analyze User Website Visit Pattern
    [LeetCode] 636. Exclusive Time of Functions
  • 原文地址:https://www.cnblogs.com/dangjingwei/p/12388788.html
Copyright © 2020-2023  润新知