本篇主要是讨论的是python中的asyncio,不是多线程,同时也不是多进程,更加不是多核运行,asyncio 是单核心、单进程、单线程下的操作。
核心概念
- event loop: 事件循环
可以理解为一个列表,列表里面放着很多个待完成的事件,又称为可等待对象。 - 可等待对象
可等待对象就是event loop 里面需要执行的对象,通过await
进行等待。这个对象可以是协程, 任务 和 Future。 - 协程
凡是在函数前面写了async
都叫协程。#这就是协程 async def hello(): return 0
- 任务
Task可以通过async.create_task()
函数创建,而这个参数的输入为一个协程。 - Future
Future
是一种特殊的 低层级 可等待对象,表示一个异步操作的 最终结果。
概念关系
以下均为个人理解
一个可等待对象可以有就绪,等待两种状态;
- event loop查看各个可等待对象的状态,当对象处于就绪状态时,event loop 交出cpu控制权,可等待对象拿到控制权。
- 可等待对象执行,进入可等待对象的cpu运行阶段。
- 当遇到将对象设置为等待状态的程序语句时,返回event loop,记录可等待对象的当前运行位置。
- 当可执行对象程序完成时,event loop将可等待对象移除event列表。
- 重复进行1、2操作,直到可等待对象全部进入等待状态或者移除event列表,此时的event loop不断循环,cpu被其占据。
理论上来说,这时候应该是死循环,因为cpu都被event loop占据,都没时间去运行可执行对象,可执行对象停止运行的状态下又无法修改可等待对象的等待状态。
所以,一定是存在外援,外援将可等待对象的等待状态修改为就绪状态,这样event loop再次进入可等待对象,重复1、2。
而这个外援是谁嘞?我不清楚,但是一般在IO情况下它会出现,比如获取网页和读取硬盘数据。
来尝试讲故事来描述吧!
打工人张三一个人负责村上的所有小作坊的工作,有5家面馆、2家照相馆和1所衣服加工厂。
之前张三是这么干活的,来到面馆,和面30分钟,拉面10分钟,烧水30分钟,煮面10分钟,端上桌子5分钟,一趟下来85分钟,干完这家去下一家面馆继续干。因此,光是面馆就要做425分钟。
来到照相馆,照相馆要求一天必须至少拍3个人,但是有时候人来的早,有时候人来的迟,照一张相很快啊,就10分钟,三个人总共就30分钟,但是等的时间长啊,一般要等120分钟,所以两家照相馆一共要花300分钟。
还有一家衣服加工厂,这里需要做10件衣服,张三是熟练工,大概10分钟一件,所以100分钟就做完了。
打工人张三一天需要整整工作825分钟,非常辛苦。
但是,有一天来了一个好心人小福,他和张三说:“我来帮帮你吧,但是我只会一些简单的活。就会看看时间,看看有没有人来什么的,其他的我都不会。”
新的一天开始了,张三刚出门就发现,8个店铺门外都挂了各个牌子,上面写着“加油吧,打工人!”,张三好奇地进面馆去和面、拉面,打算烧水,刚烧上水,小福说:“三哥,这边我来看着,你先去别的面馆吧!”,并且出去把门外的牌子翻了个面,上面写着“打工人,打工魂,打工都是人上人!”。
就这样,张三去了下一个面馆,牌子上写着“加油吧,打工人!”,张三就这样进去依旧和面、拉面,等烧水的时候,小福又出来了,“大哥,这边我看着,你再出去看看”。张三只得摸摸脑袋出来了,“这是在干么?”。张三回头一看这面馆的牌子又翻面了:“打工人,打工魂,打工都是人上人!”
张三再活动活动脑袋,突然发现第一个面馆的牌子又给转回来了“加油吧,打工人!”。张三进去一看,小福居然在面馆里面,张三不由得疑惑道:“你不是在那边么?”小福笑道:“害,过来一会了,这水都烧开10分钟了,下面吧”,张三顾不得其他,开始下面,当把手上两缕面给放到锅里,小福又催促着让张三出去了,并把门外牌子翻了个面。
就这样,每次需要烧水、煮面的时候,小福就会冒出来,让张三出去,并把牌子翻面为“打工人,打工魂,打工都是人上人!”。张三也不断找着“加油吧,打工人!”的牌子的店面,这样的店面里面小福才不让他出去。
就这样,一天工作下来,所有任务完成临天黑还有一段时间。张三同时感叹道:“要不是小福,今天还得在照相馆无所事事两个小时,小福帮我看着有没有人来,我直接就去拍照了,真方便!”
小福帮张三节约了大量时间,为了感谢小福,张三在得知小福是工地承包商,又去小福的工地帮忙砌墙,好心人小福当然不好意思让张三白白干活,也给张三一些报酬。
就这样,张三由于过度劳累,因身体不适提前下岗了。