(12)协程

什么是协程:就是低消耗的线程

我们想要开启多任务,但是消耗要比线程更低,这样就诞生了协程(单线程下实现并发的效果,这种效果就是协程)

协程的目的:就是单线程实现并发

协程的优点:相对于操作系统内置的控制cpu切换的程序消耗少一点

协程的缺点:如果程序里面需要使用到协程,必须监控程序里面所有的IO情况,如果不做处理,后面所有的任务都不会执行(因为是单线程,单任务,所以cup无法切换)

什么时候使用协程:又以下实例可以得知,在单线程下,遇到IO的时候比较合适,如果没有IO则串行的执行效率要比协程高

协程使用场景实例
import time

'''基于yield的协程'''
def func1():
while True:
print('func1')
yield


def func2():
g = func1()
for i in range(10000000):
print('func2')
next(g)


start = time.time()
func2()
print('协程的执行时间:',time.time() - start)


'''串行的执行时间,用来和协程的执行耗费对比'''
def func3():
for i in range(10000000):
pass

def func4():
for i in range(10000000):
pass

start = time.time()
func3()
func4()
print('串行的执行时间:',time.time() - start)

开启协程:通过gevent包来实现协程(这个包实第三方包)

import time

import gevent # 通过这个gevent模块来实现单线程下的协程

'''模拟现实中的协程'''


def eat(name):
print('%s is eat 1' % name)
   '''gecent只监控自己所在的任务下的IO情况'''
gevent.sleep(1) # 如果使用gevent模块,则sleep功能就不能用time模块下的,必须使用gevent模块下的sleep
print('%s is eat 2' % name)


def play(name):
print('%s is play 1' % name)
gevent.sleep(2)
print('%s is play 2' % name)


'''实例化gevent模块,提交函数spawn里面可以传入参数,一个是需要执行的任务名称,一个是传入的name名称'''
start = time.time()
g1 = gevent.spawn(eat, 'zekai') # gevent模块下的spawn就是用来提交上面函数任务的,异步的执行
g2 = gevent.spawn(play, 'steven')
g1.join() # 使用join来等待协程执行完
g2.join()

print('执行时间:', time.time() - start)

PS:主线程开启后就先执行了g1,然后由于协程是异步的,所以也同时开启了g2,主线程也在往下运行,这时候g1在执行任务的时候遇到了IO,g1遇到IO的时候g2也在执行,这时候g2也遇到了IO,然后再g2执行IO的时候g1的IO执行完了(g1所有的程序都成功执行),由于我们不知道协程什么时候执行完,为了让程序能够完整的执行,需要用到join函数来等待协程执行完毕,主线程再往下执行

开启协程:通过gevent包来实现协程(监控程序下所有的IO情况)

import time

import gevent # 通过这个gevent模块来实现单线程下的协程
from gevent import monkey #要实现监控程序下所有的IO情况需要从gevent包内倒入monkey模块

monkey.patch_all() #开启监控程序里所有IO的情况
def eat(name):
print('%s is eat 1' % name)
time.sleep(1) # 如果使用gevent模块,则sleep功能就不能用time模块下的,必须使用gevent模块下的sleep
print('%s is eat 2' % name)


def play(name):
print('%s is play 1' % name)
time.sleep(2)
print('%s is play 2' % name)


'''实例化gevent模块,提交函数spawn里面可以传入参数,一个是需要执行的任务名称,一个是传入的name名称'''
start = time.time()
g1 = gevent.spawn(eat, 'zekai') # gevent模块下的spawn就是用来提交上面函数任务的,异步的执行
g2 = gevent.spawn(play, 'steven')
g1.join() # join会等待所有协程(子线程、子进程)执行完毕再执行主线程(主进程)
g2.join()

print('执行时间:', time.time() - start)

 

原文地址:https://www.cnblogs.com/shizhengquan/p/10297822.html