协程
- 协程
协程是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。协程不是被操作系统内核管理,而是完全由程序所控制。线程和进程的操作是由程序触发系统接口,最后的执行者是系统,协程的操作是程序员。 - 意义:对于多线程的应用,CPU通过切片的方式来切换协程之间的执行,线程之间的切换需要耗时(保存状态,下次继续)。协程则只使用一个线程(单线程),在一个线程中规定某个代码快执行顺序。
- 协程的应用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程
理解:在一个线程中的某个函数,可以在任何地方保存函数的一些临时变量,然后切换到另外一个函数,注意不是通过调用函数的方式做到,并且切换的次数以及何时切换都是由程序员掌控。协程就是可以暂停执行的函数。 - 协程的简单实现
"""
1.创建work1的生成器
2.获取work2的生成器
3.获取生成器,通过next运行生成器
"""
# 1.创建work1的生成器
import time
def work1():
while True:
print('正在执行work1...')
yield
time.sleep(1)
def work2():
while True:
print('正在执行work2...')
yield
time.sleep(1)
if __name__ == '__main__':
w1 = work1()
w2 = work2()
while True:
next(w1)
next(w2)
上面的程序就实现了一个简答的协程。实现单线程两个任务同时切换。
4. greenlet
Greenlet是python的一个C扩展,可以提供可自行调度的微线程,也就是协程。
"""
1.创建work1的生成器
2.获取work2的生成器
3.获取生成器,通过next运行生成器
"""
"""
greenlet实现协程的步骤
1.导入模块
2.创建任务work1,work2
3.创建greenlet对象
4.手动切换任务
"""
# 1.创建work1的生成器
import time
from greenlet import greenlet
def work1():
while True:
print('正在执行work1...')
yield
time.sleep(1)
# 切换到第二个任务
g2.switch()
def work2():
while True:
print('正在执行work2...')
yield
time.sleep(1)
# 切换到第一个任务
g1.switch()
if __name__ == '__main__':
# 创建greenlet对象
g1 = greenlet(work1)
g2 = greenlet(work2)
# 执行work1
g1.switch()
5. grvent
由于IO操作非常耗时,经常使程序处于等待状态,有了grevent为我们自动切换协程,就保证greenlet在运行,而不是等待IO。
"""
# 自动识别程序中耗时操作,在耗时的时候自动切换到其他任务
1.导入模块
2.指派任务
"""
# 1.创建work1的生成器
import time
import gevent
def work1():
while True:
print('正在执行work1...')
gevent.sleep(1)
def work2():
while True:
print('正在执行work2...')
# gevent识别不了,time.sleep()是延时操作
# time.sleep(1)
gevent.sleep(1)
if __name__ == '__main__':
# 指派任务
# gevent.spawn(函数名,参数1,参数2,参数3,....)
g1 = gevent.spawn(work1)
g2 = gevent.spawn(work2)
# 让主线程等待协程执行完毕再退出
g1.join()
g2.join()
上面的程序中gevent识别不了time.sleep()是延迟操作,因此有可以使用打补丁的方法:
1. 导入模块
from gevent import monkey2. 破解monkey.patch_all()
monkey.patch_all()
上面两步完成之后,就可以识别了。