介绍-> 阻塞和非阻塞
阻塞:从调用者的角度出发,如果在调用的时候,被卡住,不能再继续向下运行,需要等待,就说是阻塞
非阻塞:从调用者的角度出发, 如果在调用的时候,没有被卡住,能够继续向下运行,无需等待,就说是非阻塞
三、使用yield完成多任务
yield特点:
1.将数据返回出来,
2.返回数据之后,进行暂停挂起机制
3.下一次启动时,从哪里暂停,就从哪里开始
def play():
'''玩游戏'''
while True:
print('玩游戏 .....')
time.sleep(.5)
yield # 没有返回值的情况下,起到暂停挂起的效果
def network():
'''上网'''
while True:
print('上网.....')
time.sleep(.5)
yield # 没有返回值的情况下,起到暂停挂起的效果
#通过方法调用
def main():
p=play() # 生成器对象,next()就可以调用一次生成器模板
n=network()
# next(p) # 变成了非阻塞状态
# next(n)
#它们执行一次,就暂停了!那么就必须使用循环了哦!
while True:
next(p) # 变成了非阻塞状态
next(n)
if __name__=='__main__':
main()
小结:
yield完成多任务: 一个进程, 一个线程: 占用的资源最少。 利用的是yield暂停挂起的机制,让程序变成非阻塞的效果,从而达到可以切换任务的目的,进行多任务。
其实就是一个假的多任务:是单线程 利用的是yield的挂起机制,让程序变成非阻塞状态,以此来切换任务。 类似多线程CPU的切换。
四、使用greenlet完成多任务
greenlet 是对yield进程了封装 它是第三方库 pip install greenlet -i https://pypi.douban.com/simple 可以在Terminal 查看 pip list 回车 如果还是没有,可以重启pycharm哦!
from greenlet import greenlet
import time
def play():
'''玩游戏'''
while True:
print('玩游戏 .....')
time.sleep(.5)
#手动切换-network
gl2.switch()
def network():
'''上网'''
while True:
print('上网.....')
time.sleep(.5)
# 手动切换-play
gl1.switch()
def main():
gl1.switch() #进行切换,切换到对象的指向部分
if __name__=='__main__':
#创建greenlet对象,对yield进行了封装
gl1= greenlet(play) #创建对象,指向了play函数
gl2= greenlet(network) #创建对象,指向了network函数
main()
效果同上:忽略
小结:greenlet实现多任务的原理,让程序变成非阻塞,,来回切换任务,达到多任务的效果.
五、使用gevent完成多任务
第三方库
greentlet >yield
gevent > greenlet
from gevent import monkey
import time
#打补丁
monkey.patch_all() #只要执行这个代码,程序中的延时操作,就会骗过gevent,让它看成自己的延时
def play():
'''玩游戏'''
for i in range(1,6):
print(f'玩第{i}个游戏')
time.sleep(.5)
def network():
'''上网'''
for i in range(1,6):
print(f'网冲浪第{i}个')
time.sleep(.5) #通过打补丁的方式,骗过gevent,当作正常的延时。
#通过方法调用
def main():
gv1.join() #类似于启动
gv2.join() #类似于启动
if __name__=='__main__':
#使用gevent进行任务
gv1=gevent.spawn(play)
gv2=gevent.spawn(network)
main()
说明:无法避免的延迟操作(协程进行任务切换哦) (1) 网络延迟 (2) 文件读写
小结:gevent原理: 单进程,单线程的情况下,让程序一旦碰到延时操作就自动进行任务的切换,变成非阻塞状态。