原文地址:Futures - Isolates - Event Loop
原文作者:www.didierboelens.com
译文出自:掘金翻译计划
本文永久链接: https:// github.com/xitu/gold-mi ner/blob/master/TODO1/futures-isolates-event-loop.md
译者:nanjingboy
校对者:sunui, Fengziyin1234
Flutter 异步编程:Future、Isolate 和事件循环
本文介绍了 Flutter 中不同的代码执行模式:单线程、多线程、同步和异步。
难度:中级
概要
我最近收到了一些与 Future、async、await、Isolate 以及并行执行概念相关的一些问题。
由于这些问题,一些人在处理代码的执行顺序方面遇到了麻烦。
我认为通过一篇文章来解释异步、并行处理这些概念并消除其中任何歧义是非常有用的。
Dart 是一种单线程语言
首先,大家需要牢记,Dart 是单线程的并且 Flutter 依赖于 Dart。
重点 Dart 同一时刻只执行一个操作,其他操作在该操作之后执行,这意味着只要一个操作正在执行,它就 不会被其他 Dart 代码中断。
也就是说,如果你考虑纯粹的同步方法,那么在它完成之前,后者将是唯一要执行的方法。
void myBigLoop(){
for (int i = 0; i < 1000000; i++){
_doSomethingSynchronously();
}
}
在上面的例子中,myBigLoop() 方法在执行完成前永远不会被中断。因此,如果该方法需要一些时间,那么在整个方法执行期间应用将会被阻塞。
Dart 执行模型
那么在幕后,Dart 是如何管理操作序列的执行的呢?
为了回答这个问题,我们需要看一下 Dart 的代码序列器(事件循环)。
当你启动一个 Flutter(或任何 Dart)应用时,将创建并启动一个新的线程进程(在 Dart 中为 「Isolate」)。该线程将是你在整个应用中唯一需要关注的。
所以,此线程创建后,Dart 会自动:
- 初始化 2 个 FIFO(先进先出)队列(「MicroTask」和 「Event」);
- 并且当该方法执行完成后,执行 main() 方法,
- 启动事件循环。
在该线程的整个生命周期中,一个被称为事件循环的单一且隐藏的进程将决定你代码的执行方式及顺序(取决于 MicroTask 和 Event 队列)。
事件循环是一种无限循环(由一个内部时钟控制),在每个时钟周期内,如果没有其他 Dart 代码执行,则执行以下操作:
void eventLoop(){
while (microTaskQueue.isNotEmpty){
fetchFirstMicroTaskFromQueue();
executeThisMicroTask();
return;
}
if (eventQueue.isNotEmpty){
fetchFirstEventFromQueue();
executeThisEventRelatedCode();
}
}
正如我们看到的,MicroTask 队列优先于 Event 队列,那这 2 个队列的作用是什么呢?
MicroTask 队列
MicroTask 队列用于非常简短且需要异步执行的内部动作,这些动作需要在其他事情完成之后并在将执行权送还给 Event 队列之前运行。
作为 MicroTask 的一个例子,你可以设想必须在资源关闭后立即释放它。由于关闭过程可能需要一些时间才能完成,你可以按照以下方式编写代码:
MyResource myResource;
...
void closeAndRelease() {
scheduleMicroTask(_dispose);
_close();
}
void _close(){
// 代码以同步的方式运行
// 以关闭资源
...
}
void _dispose(){
// 代码在
// _close() 方法
// 完成后执行
}
这是大多数时候你不必使用的东西。比如,在整个 Flutter 源代码中 scheduleMicroTask() 方法仅被引用了 7 次。
最好优先考虑使用 Event 队列。
Event 队列
Event 队列适用于以下参考模型
- 外部事件如