二十、协程

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

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

‘‘‘yield的使用‘‘‘#函数中存在yield表示是一个生成器generatordef 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,timenow=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()# 创建任务tasktask=loop.create_task(foo(3))print(task)#状态为pendingprint(‘如果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 1start=time.time()#创建事件循环loop=asyncio.get_event_loop()# 创建任务tasktask=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 xstart=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 xasync 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 xasync 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()

原文地址:https://www.cnblogs.com/dangjingwei/p/12388788.html

时间: 2024-10-12 08:42:05

二十、协程的相关文章

python并发编程(二):协程

'''协程: 1. 协程的定义: 1) 是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 2) 是一种协作而非抢占式的处理并发方式, A --> B ---> A --> C 3) 协程的切换属于程序级别的, 操作系统不需要切换 2. 协程的特点: 1) 协程本身是一个线程, 是用户态的切换 2) 相比线程优点: 1> 切换没有消耗 2> 修改共享程序不需要加锁 3) 相比线程缺点: 一旦引入协程,就需要检测单线程下所有的IO行为, 实现遇到IO就切换,少一个都不

第十二篇:多任务之协程(三)

本篇主要介绍协程相关知识,但是在学习协程之前我们需要对迭代器和生成器做更加深入的了解,随后关于实现协程的方式进行了解,其中关于生成器.greenlet模块.gevent模块(重点),最后便是关于进程.线程.携程的总结. 一.迭代器 关于迭代器已经在前面的文件中进行了介绍,但是分类是放在python的函数进阶中,在这里我们会纠正这个说法,详情请点击>>> 可迭代对象和迭代器对象: 可迭代对象:简单来说,可以被for循环遍历的对象即为可迭代对象,当然也可以说拥有__iter__()方法的对象

lua编程之协程介绍

一,lua协程简介 协程(coroutine),意思就是协作的例程,最早由Melvin Conway在1963年提出并实现.跟主流程序语言中的线程不一样,线程属于侵入式组件,线程实现的系统称之为抢占式多任务系统,而协程实现的多任务系统成为协作式多任务系统.线程由于缺乏yield语义,所以运行过程中不可避免需要调度,休眠挂起,上下文切换等系统开销,还需要小心使用同步机制保证多线程正常运行.而协程的运行指令系列是固定的,不需要同步机制,协程之间切换也只涉及到控制权的交换,相比较线程来说是非常轻便的.

35、concurrent.futures模块与协程

concurrent.futures  -Launching parallel tasks    concurrent.futures模块同时提供了进程池和线程池,它是将来的使用趋势,同样我们之前学习的进程池Pool和threadpool模块也可以使用. 对进程池疑惑的可以参阅:32进程池与回调函数http://www.cnblogs.com/liluning/p/7445457.html 对threadpool模块疑惑的可以看我闲暇时写的一段代码:(因为本人也不了解这个模块,代码里写的也是自己

lua学习笔记13:协程具体解释和举例

一.coroutine.create创建协程 參数是协程的主函数,返回一个thread对象 co = coroutine.create(function() print("coroutine execute!") end) 二.协程状态 协程有三种状态:挂起(suspended).执行(running)和死亡(dead) coroutine.status(co)返回协程当前的状态 协程创建完之后处于挂起状态 print(coroutine.status(co)) 输出: suspend

lua学习笔记12:协程详解和举例

一.coroutine.create创建协程 参数是协程的主函数,返回一个thread对象 co = coroutine.create(function() print("coroutine execute!") end) 二.协程状态 协程有4种状态:挂起(suspended).运行(running).死亡(dead)和正常(normal) coroutine.status(co)返回协程当前的状态 协程创建完之后处于挂起状态 print(coroutine.status(co))

[转载]协程-cooperative multitasking

[转载]协程三讲 http://ravenw.com/blog/2011/08/24/coroutine-part-1-defination-and-classification-of-coroutine/ http://ravenw.com/blog/2011/09/01/coroutine-part-2-the-use-of-coroutines/ http://ravenw.com/blog/2011/09/06/coroutine-part-3-coroutine-and-continu

python并发之多进程、多线程、协程和异步

一.多线程 二.协程(又称微线程,纤程) 协程,与线程的抢占式调度不同,它是协作式调度.协程在python中可以由generator来实现. 首先要对生成器和yield有一个扎实的理解. 调用一个普通的python函数,一般是从函数的第一行代码开始执行,结束于return语句.异常或者函数执行(也可以认为是隐式地返回了None). 一旦函数将控制权交还给调用者,就意味着全部结束.而有时可以创建能产生一个序列的函数,来“保存自己的工作”,这就是生成器(使用了yield关键字的函数). 能够“产生一

concurrent.futures模块与协程

concurrent.futures  -Launching parallel tasks    concurrent.futures模块同时提供了进程池和线程池,它是将来的使用趋势,同样我们之前学习的进程池Pool和threadpool模块也可以使用. 对进程池疑惑的可以参阅:32进程池与回调函数http://www.cnblogs.com/liluning/p/7445457.html 对threadpool模块疑惑的可以看我闲暇时写的一段代码:(因为本人也不了解这个模块,代码里写的也是自己

python开发concurent.furtrue模块:concurent.furtrue的多进程与多线程&协程

一,concurent.furtrue进程池和线程池 1.1 concurent.furtrue 开启进程,多进程&线程,多线程 1 # concurrent.futures创建并行的任务 2 # 进程池 ProcessPoolExecutor,ThreadPoolExecutor 3 # 下面例子是Io密集型,所以时间上比叫多 4 from concurrent.futures import ProcessPoolExecutor 5 import os,time,random 6 def t