3.4.3协程
(1)协程: 又称为微线程,用户级线程, 在不开辟线程的基础上可以完成多任务
(2)如何理解协程: 只要在def里面只看到一个yield关键字那么就可以理解为是一个协程
(3)学习协程的目的: 在单线程的基础上完成多任务,多个任务按照一定顺序交替执行
(4)定义、创建、启动协程
import time
# 定义协程
def work1():
while True:
print("work1…")
time.sleep(0.2)
yield
# 定义协程
def work2():
while True:
print("work2…")
time.sleep(0.2)
yield
if __name__ == '__main__':
# 创建协程
g1 = work1()
g2 = work2()
while True:
# 启动协程
next(g1)
next(g2)
(5)greenlet的使用
greenlet是对协程进行了封装,能够让程序员更加清楚地知道协程如何切换执行
例如:
import greenlet
import time
# 任务1
def work1():
for i in range(10):
print("work1...")
time.sleep(0.2)
# 切换到协程2执行对应的代码
g2.switch()
# 任务2
def work2():
for i in range(10):
print("work2...")
time.sleep(0.2)
# 切换到协程1执行对应的代码
g1.switch()
if __name__ == '__main__':
# 创建协程
g1= greenlet.greenlet(work1)
# 创建协程
g2 = greenlet.greenlet(work2)
# 切换到协程1执行对应的任务
g1.switch()
(6)gevent的使用
import gevent
import time
from gevent import monkey
# 打补丁,让gevent能够识别系统耗时操作,比如:time.sleep,网络请求延时
# 打补丁操作要先执行
monkey.patch_all()
# 任务1
def work1():
for i in range(10):
print("work1…")
time.sleep(0.2)
#gevent.sleep(0.2)
# 任务2
def work2():
for i in range(10):
print("work2…")
time.sleep(0.2)
#gevent.sleep(0.2)
if __name__ == '__main__':
# 创建协程并指派任务
g1 = gevent.spawn(work1)
# 创建协程并指派任务
g2 = gevent.spawn(work2)
# 主动让线程等待两个协程执行完成以后程序在退出
g1.join()
g2.join()
#也可写成:
#gevent.joinall([g1, g2])
(7)进程、线程、协程对比
①进程是操作系统资源分配的基本单位
②线程是cpu调度的基本单位,调度那个线程,那个线程执行对应的代码
③多进程开发比单进程多线程开发稳定性要强,但是多进程开发占用的资源更多
④进程之间不共享全局变量,线程之间共享全局变量,提示:多线程共享全局变量要注意资源竞争的问题,解决办法:互斥锁,线程同步
⑤线程之间执行是无序的,协程是按照一定顺序交替执行的
⑥开辟一个协程大概需要5k,开辟一个线程需要512k,开辟进程需要资源是最大的
⑦协程以后的使用场景: 网络爬虫,网络请求
⑧三者之间的关系是:先有进程,进程里面默认提供一个线程,线程里面可以包含多个协程