• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
菩提叶子
博客园    首页    新随笔    联系   管理    订阅  订阅
python协程

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

 

posted on 2022-10-26 18:53  菩提叶子  阅读(211)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3