0%

python | 事件循环

说实话,我目前对这一块的理解并不深刻,只能是通过我自己的使用进行总结,当然,随着时间的推移和更新,这篇文章的内容会越来越对。


参考资料



举个例子


假设一个厨房正在生产菜。每一个菜后面都有一个做菜的师傅,每一个做菜的师傅都有一个切配、杂手等。

切配来切各种食材,杂手准备各种厨具,同时做菜的师傅至少掌管 2 个锅。

如果将该灶台抽象为一个线程,那么做菜的师傅可以称之为一个事件循环(Event Loop),而锅可以认为是事件循环中的任务,切配、杂手是处理任务的。

  • 一个菜名送过来「任务注册到事件循环中」
  • 大厨看到菜名「事件循环开始工作」
  • 切配准备「IO 准备」
  • 切配准备好了,告知大厨「唤醒相关任务」
  • 大厨完成这道菜「任务结束」

那异步的优势是什么呢?

  • 可以有多个任务注册到事件循环中「有多个锅」
  • 如果遇到 IO 堵塞,可以执行其他事件循环的任务「当切配准备时,大厨可以做已经准备好的菜」
  • 成本低,上下文切换快「如果你换一个灶台,还需要跑来跑去,但是,你灶台有两个锅」

除了上述之外,还有几个隐藏的点

  • 每一个线程都可以有一个事件循环「灶台后面有一个大厨」
  • 每一个线程只能有一个事件循环「一道菜只能由一个大厨做」

事件循环


1
2
3
4
while 1:
for task in tasks:
if task.state == "ready":
task.run()

事件循环就是在 loop 没有结束的时候,会一直循环里面已经注册的任务,直到遇到特定条件来终止循环。

while 不同的是,里面的 task 有很多状态,结束、运行、挂起等。

一个网络请求任务注册到事件循环中,当网络正在请求的时候,事件循环会去执行其他任务,当请求过来之后,会唤醒该任务。

另外一个重要的事情是,协程可以简单的理解为某一道菜,它是依附于大厨,即事件循环的,不能独立执行。

如果,你想做菜,那么你需要准备一个大厨。

如果事件循环结束,比如,你在线程中创建一个事件循环,后面再调用的话是非法的。大厨走了,你给菜名并不能做菜。

不同线程的事件循环并不能使用,线程能用只有自己的事件循环。将面点给炒菜的,是不行的。

1
2
3
4
import asyncio

loop = asyncio.get_event_loop()
loop.run_until_complete("任务")
请我喝杯咖啡吧~