单线程并发——协程
Posted chenliang0309
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单线程并发——协程相关的知识,希望对你有一定的参考价值。
1. 什么是协程
协程,英文名称为 Coroutine,经常被称为微线程,纤程,是一种多任务并发的操作手段
PYTHON 中的多任务处理,根据资源消耗情况可以选择多进程并发、多线程并发,同时也可
以在节省系统资源的情况下选择协程并发,协程由于是工作在一个线程中的执行单元,所以
系统资源消耗是最少的
定义:协程是运行在单线程中的并发程序!
由于协程省去了多线程、多进程并发机制下的切换管理和状态数据管理等,所以操作效率较
高,PYTHON 不同的版本中提供了不少关于协程的支持,我们从最简单的多任务并发逐步深
入了解 PYTHON 中的协程
2.python中gevent模块下多任务操作协程
协程既然是多任务并发,肯定是参考了多线程的工作机制,我们安装 gevent 模块完成最基
本的多任务操作协程
pip install gevent
3 协程:多任务手工切换
我们回到最初的多任务并发,要求在程序中一边唱歌一边跳舞的功能实现
import time
from greenlet import greenlet
def sing():
# 定义唱歌的函数
while True:
print("唱歌》》》")
time.sleep(1)
# 切换运行协程2
g2.switch()
def dance():
while True:
print("跳舞》》》》")
time.sleep(1)
# 切换运行协程1
g1.switch()
if __name__ == "__main__":
# 创建两个协程对象
g1 = greenlet(sing)
g2 = greenlet(dance)
# 切换到协程1工作
g1.switch()
print("主进程执行...")
4 协程:多任务自动切换
我们通过事件操作模块gevent,让多个任务根据自己的运行状态进行自动切换
import gevent
import threading
def sing():
# 定义唱歌函数
while True:
print("唱歌>>>", threading.current_thread().getName())
# 事件休眠,让出执行时间片
gevent.sleep(1)
def dance():
# 定义跳舞函数
while True:
print("跳舞>>>", threading.current_thread().getName())
# 事件休眠,让出时间片
gevent.sleep(3)
if __name__ == "__main__":
# 常见跳舞、唱歌的协程
s = gevent.spawn(sing)
d = gevent.spawn(dance)
# 独占时间片运行
s.join()
d.join()
执行代码运行程序,可以看到他们是工作在一个线程中的执行单元
5 协程:基于python生成器对象的多任务
Python 中为了有效的利用内存进行程序的运算操作,提供了一个生成器对象 yield
所谓生成器,就是在程序运行执行到该代码时才参与运算得到结果,经常被用作协程操作和
组合数据类型的推导生成
由于其执行即运算的特性,通过生成器操作也可以完成协程的处理
import time
def sing():
while True:
time.sleep(1)
print("唱歌》》》")
yield
def dance():
while True:
time.sleep(1)
print("跳舞>>>")
next(s)
if __name__ == "__main__":
s = sing()
d = dance()
生成器对象主要的核心函数就是next(),通过next()方法才能执行运算得到运算的下一个结果值,所以这里有效的利用yield完成了一次协程的工作。但是毕竟yield错做协程的可读性较差。
6 协程:python3.4+版本
PYTHON3.4 版本中添加了异步 io 操作模块 asyncio,对于协程的操作支持就变得比较友好
了,通过异步 io 操作,可以将多路 io 程序通过协程的方式提升操作效率
import asyncio
# 添加一个注解,标注这个函数是一个协程函数
@asyncio.coroutine
def show_info(name):
for i in range(0, 10):
print(name, "输出数据>>>")
# 异步执行代码,模拟耗时2s
yield from asyncio.sleep(2)
if __name__ == "__main__":
# 获取异步IO时间轮询对象
loop = asyncio.get_event_loop()
# 编译执行
loop.run_until_complete(asyncio.gather(show_info("tom"), show_info("jerry")))
# 关闭时间 轮询
loop.close()
前面那个唱歌跳舞的异步IO协程改版
import asyncio
@asyncio.coroutine
def sing():
while True:
print("唱歌》》》")
yield from asyncio.sleep(2)
@asyncio.coroutine
def dance():
while True:
print("跳舞》》》")
yield from asyncio.sleep(2)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(sing(), dance()))
loop.close()
7 python3.5版本
PYTHON3.5 又增加了新的操作机制以提高对协程的支持
新增 async 替代了原来的@asyncio.corotine,新增 await 替代了原有的 yield from 步骤,简
化和优化了原有协程处理流程,这一部分异步操作,在以后的各个需要异步操作的方面都有
着非常广泛的应用。
import asyncio
async def sing():
while True:
print("唱歌》》》")
# 异步操作
await asyncio.sleep(2)
async def dance():
while True:
print("不如跳舞》》》")
await asyncio.sleep(1)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(sing(), dance()))
loop.close()
以上是关于单线程并发——协程的主要内容,如果未能解决你的问题,请参考以下文章