昨日内容回顾
协程实际上是一个线程,执行了多个任务,遇到IO就切换
切换,可以使用yield,greenlet
遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻塞问题。
昨天没有讲到的小问题,看下面的例子:
import gevent def func(): print('eating') gevent.spawn(func) # 协程任务开启
执行程序,没有输出结果
加上join
import gevent def func(): print('eating') g = gevent.spawn(func) g.join() # 阻塞,等待协程执行完毕
执行输出:eating
加上睡眠
import time import gevent def func(): print('eating') g = gevent.spawn(func) time.sleep(1) # 等待1秒
执行程序,没有输出结果
使用gevent.sleep()
import gevent def func(): print('eating') g = gevent.spawn(func) gevent.sleep(1)
执行输出:eating 然后过1秒退出
导入monkey模块,再使用内置的time.sleep()
from gevent import monkey;monkey.patch_all() import time import gevent def func(): print('eating') g = gevent.spawn(func) time.sleep(1)
执行输出:eating
修改为sleep(0)
from gevent import monkey;monkey.patch_all() import time import gevent def func(): print('eating') g = gevent.spawn(func) time.sleep(0)
执行输出:eating
time.sleep(0)虽然时间为0,它也是阻塞,gevent检测到了IO
总结:
协程任务开启,不会立即执行,它需要IO才能执行
from gevent import monkey;monkey.patch_all() import time import gevent def func(): print('eating1') # 执行 time.sleep(0.1) # 遇到IO print('eating2') time.sleep(0.1) print('eating3') time.sleep(0.1) g = gevent.spawn(func) # 协程任务开启 time.sleep(0) # 阻塞遇到IO
执行输出:eating1
结果为什么时eating1?下面的2和3为啥不执行呢?
因为time.sleep(0)比time.sleep(0.1)要快,执行之后,就结束了。
切换到主进程时,发i西安主进程已经结束了。所以eating2和eating3没有执行。
如果用join‘,就可以让eating2和etaing3执行
from gevent import monkey;monkey.patch_all() import time import gevent def func(): print('eating1') # 执行 time.sleep(0.1) # 遇到IO print('eating2') time.sleep(0.1) print('eating3') time.sleep(0.1) g = gevent.spawn(func) # 协程任务开启 #time.sleep(0) # 阻塞遇到IO g.join() # 等待协程结束
执行输出:
总结:
内部执行switch时,必须保证协程不结束之前,主线程不结束
在昨天的socket例子中,没有用到join
因为accept时永久 阻塞,他不需要join
并发编程,在面试和重要。一定要熟练掌握
一、IO模型介绍
为了更好地了解IO模型,我们需要事先回顾下:同步、异步、阻塞、非阻塞