1、概念
协程,又称微线程。协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
2、协程和现成的差异
在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。
3、协程实现方法
1)、带有yield的函数不再是普通函数,而是生成器。send可以把一个函数的结果传给另外一个函数,以此实现单线程内程序之间的切换
2)、asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
4、协程改写生产者消费者模型
# 生产者 def prodecer(): for i in range(100): yield i # 消费者 def consumer(gen): for i in range(10): print(next(gen)) # 初始化生成器函数 -> 生成器 gen = prodecer() consumer(gen) consumer(gen) consumer(gen)
5、python使用gevent实现协程
import gevent def eat(): print("eat 1") gevent.sleep(3) # time.sleep(3) print("eat 2") def play(): print("play 1") gevent.sleep(3) # time.sleep(3) print("play 2") # 利用gevent.spawn创建协程对象g1 g1 = gevent.spawn(eat) # 利用gevent.spawn创建协程对象g2 g2 = gevent.spawn(play) # 如果不加join阻塞,默认主线程执行时,不等待直接结束. # 阻塞,必须等待g1协程任务执行完毕之后,放行 g1.join() # 阻塞,必须等待g2协程任务执行完毕之后,放行 g2.join()
6、gevent可以实现切换,不能识别time.sleep阻塞
from gevent import monkey monkey.patch_all() import time import gevent def eat(): print("eat 1") time.sleep(3) print("eat 2") def play(): print("play 1") time.sleep(3) print("play 2") # 利用gevent.spawn创建协程对象g1 g1 = gevent.spawn(eat) # 利用gevent.spawn创建协程对象g2 g2 = gevent.spawn(play) # 如果不加join阻塞,默认主线程执行时,不等待直接结束. # 阻塞,必须等待g1协程任务执行完毕之后,放行 g1.join() # 阻塞,必须等待g2协程任务执行完毕之后,放行 g2.join() print("主线程执行结束 ... ")
7、协程相关方法
# (1) spawn(函数,参数1,参数2... ) 启动协程 # (2) join 阻塞,直到某个协程任务执行完毕之后,在执行下面代码 # (3) joinall 等待所有协程任务都执行完毕之后,放行 g1.join() g2.join() => gevent.joinall( [g1,g2] ) (推荐) # (4) value 获取协程任务中的返回值 g1.value g2.value
标签:协程,g2,g1,python,gevent,print,join From: https://www.cnblogs.com/songyunjie/p/16829656.html