协程:(微线程)用户态轻量级线程
单线程,串行,其实质在不同的函数中快速切换,以达到并行的效果。适合io操作密集型工作中。
协程的好处:
(1)无需线程上下文切换的开销
(2)无需原子操作锁定及同步的开销
(3)方便切换控制流,简化编程模型
(4)高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
缺点:
无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多CPU上.
当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。进行阻塞(Blocking)操作(如I0时)会阻塞掉整个程序
协程知识点:
(1)greenlet :手动切换
程序会按照注释先后执行。
import greenlet
def product():
print(‘leo 来吃包子了‘) #1
g2.switch()
print("急什么急,正在做")#3
g2.switch()
print(‘急毛线,信不信我下毒‘)#5
def consumer():
print("包子呢?leo恶狠狠的说!")#2
g1.switch()
print(‘快一点,不然老子弄死你‘)#4
g1.switch()
g1 = greenlet.greenlet(product)
g2 = greenlet.greenlet(consumer)
g1.switch()
(2)gevent:自动切换,同步、异步
import gevent
def foo():
print(‘ Running in foo‘) #1
gevent.sleep(2)
print(‘ Explicit context switch to foo again‘)#6
def bar():
print(‘Explicit精确的context内容to bar‘)#2
gevent.sleep(1)
print (‘ Implicit context switch back to bar‘)#5
def run():
print("runxxxxx")#3
gevent.sleep(0)
print("run end")#4
gevent.joinall(
[gevent.spawn(foo) ,
gevent.spawn (bar),
gevent.spawn(run)])
一个非常low的爬虫demo:
from urllib import request
from gevent import monkey #把当前程序的所有的有可能是io操作单独的做上标记
import gevent
monkey.patch_all()
def f(url):
print(‘GET:%s‘%url)
resp =request.urlopen(url)
data =resp.read()
with open(‘url.html‘,‘wb‘) as f:
f.write(data)
gevent.joinall(
[gevent.spawn(f,‘http://www.cnblogs.com/alex3714/articles/5248247.html‘),
gevent.spawn(f,‘https://www.yahoo.com/‘),
gevent.spawn(f,‘https://github.com/‘),]
)
原文:https://www.cnblogs.com/gtq7512/p/11375486.html