1. 协程
-
⽐线程更⼩的执⾏单元
-
某个函数, 可以在任何地⽅保存当前函数的⼀些临时变量等信息, 然后切换到另外⼀个函数中执⾏
-
协程⾃⼰主动让出CPU
-
协程的切换只是单纯的操作CPU的上下⽂ ,比线程的切换更快速
-
1:N 模式:所谓 1:N 就是⼀个线程作为⼀个容器⾥⾯放置多个协程
-
IO密集型的程序和CPU密集型程序
2. 协程 - greenlet
- python中的greenlet模块对协程进行了封装
- 安装模块:pip install greenlet
"""
用greenlet实现协程
特点:由用户来控制的
"""
from greenlet import greenlet
import time
def fun1():
while True:
print('----func1---')
g2.switch() # 转换到fun2,然后再回到time.sleep(3)
time.sleep(3)
print('----func1 one---')
def fun2():
while True:
print('----func2---')
g1.switch()
time.sleep(3)
print('----func2 two---')
# 创建协程转换器
g1 = greenlet(fun1)
g2 = greenlet(fun2)
# 启动g1转换器
g1.switch()
3. 协程 - gevent
- python还有一个比greenlet更强大的且能够自动切换任务的模块gevent。
- 原理是当一个greenlet遇到IO(指的是input output,比如网络,文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,在适当的时候切换回来继续执行。
"""
用gevent实现协程
目前是顺序执行
这个列子不会实现协程间的切换。。
"""
import gevent
def method(n):
for i in range(n):
print(gevent.getcurrent(),i)
#创建协程
g1 = gevent.spawn(method,5)
g2 = gevent.spawn(method,5)
g3 = gevent.spawn(method,5)
g1.join()
g2.join()
g3.join()
- 实例:根据自己时间来进行协程的自动切换
"""
用gevent实现协程
体现优点:会自己根据事件来进行协程的自动切换
"""
import gevent
def method(n):
for i in range(n):
print(gevent.getcurrent(),i)
#模拟耗时操作
gevent.sleep(0.5)
#创建协程
g1 = gevent.spawn(method,5)
g2 = gevent.spawn(method,5)
g3 = gevent.spawn(method,5)
g1.join()
g2.join()
g3.join()
4. 协程 - 并发下载器
"""
并发下载器
体现gevent 会根据事件 进行协程自动切换
"""
from gevent import monkey
from urllib import request
import gevent
#需要让gevent能够自动处理IO事件,必须先打补丁
monkey.patch_all()
def download(url):
print('get:%s'%url)
response = request.urlopen(url)
# 在这进行网络的交互,在等待的时候,会把CPU交给其他任务运行,如果没有协程,会在这里卡死
data = response.read()
print(data)
print('从%s收到%d数据'%(url,len(data)))
gevent.joinall([
gevent.spawn(download,"http://www.baidu.com"),
gevent.spawn(download,"http://www.sina.com"),
gevent.spawn(download,"http://www.bjsxt.com"),])