Dart汇总请点击这里
同步代码和异步代码;
同步代码:就是一行行写下来的代码
异步代码:就是以Future等修饰的代码
这两类代码的不同
1.运行顺序不同
同步代码和异步代码运行的顺序是不同的:
先运行同步代码,在运行异步代码
复制代码就是,即使我异步代码写在最前面,同步代码写在最后面,我也是先运行后面的同步代码,同步代码都运行完后,在运行前面的异步代码。
一下代码的输出结果是什么?
import 'dart:async';
main() {
print('main #1 of 2');
scheduleMicrotask(() => print('microtask #1 of 2'));
new Future.delayed(new Duration(seconds:1),
() => print('future #1 (delayed)'));
new Future(() => print('future #2 of 3'));
new Future(() => print('future #3 of 3'));
scheduleMicrotask(() => print('microtask #2 of 2'));
print('main #2 of 2');
}
main #1 of 2
main #2 of 2
microtask #1 of 2
microtask #2 of 2
future #2 of 3
future #3 of 3
future #1 (delayed)
2.运行的机制不同
异步代码是运行在event loop里的,event loop不断的从事件队列里取事件然后运行。
Dart 的事件循环
Dart 是事件驱动的体系结构,该结构基于具有单个事件循环和两个队列的单线程执行模型。 Dart虽然提供调用堆栈。 但是它使用事件在生产者和消费者之间传输上下文。 事件循环由单个线程支持,因此根本不需要同步和锁定。
Dart 的两个队列
- MicroTask queue 微任务队列
- Event queue 事件队列
Dart事件循环执行如上图所示
- 先查看MicroTask队列是否为空,不是则先执行MicroTask队列
- 一个MicroTask执行完后,检查有没有下一个MicroTask,直到MicroTask队列为空,才去执行Event队列
- 在Evnet 队列取出一个事件处理完后,再次返回第一步,去检查MicroTask队列是否为空
注意:我们可以看出,将任务加入到MicroTask中可以被尽快执行,但也需要注意,当事件循环在处理MicroTask队列时,Event队列会被卡住,应用程序无法处理鼠标单击、I/O消息等等事件。
控制任务调度
将任务添加到MicroTask队列有两种方法
- 使用 scheduleMicrotask 方法添加
- 使用Future对象添加
import 'dart:async';
//我的任务队列
void myTask(){
print("this is my task");
}
void main() {
# 1. 使用 scheduleMicrotask 方法添加
scheduleMicrotask(myTask);
# 2. 使用Future对象添加
new Future.microtask(myTask);
}
将任务添加到Event队列
使用Future对象添加
import 'dart:async';
//我的任务
void myTask(){
print("this is my task");
}
void main() {
# 1. 使用Future对象添加
new Future(myTask);
}
验证
import 'dart:async'
void main() {
print('main Start');
new Future((){
print('this is my task');
});
new Future.microtask((){
print('this is microtask');
});
print('main Stop');
}
main start
main stop
this is microtask
this is my task
可以看到,代码的运行顺序并不是按照我们的编写顺序来的,将任务添加到队列并不等于立刻执行,它们是异步执行的,当前main方法中的代码执行完之后,才会去执行队列中的任务,且MicroTask队列运行在Event队列之前。
延时任务
如需要将任务延伸执行,则可使用Future.delayed方法
new Future.delayed(new Duration(seconds:1),(){
print('task delayed');
});
表示在延迟时间到了之后将任务加入到Event队列。需要注意的是,这并不是准确的,万一前面有很耗时的任务,那么你的延迟任务不一定能准时运行。
import 'dart:async';
import 'dart:io';
void main() {
print("main start");
new Future.delayed(new Duration(seconds:1),(){
print('task delayed');
});
new Future((){
// 模拟耗时5秒
sleep(Duration(seconds:5));
print("5s task");
});
print("main stop");
}
运行结果:
main start
main stop
5s task
task delayed
从结果可以看出,delayed方法调用在前面,但是它显然并未直接将任务加入Event队列,而是需要等待1秒之后才会去将任务加入,但在这1秒之间,后面的new Future代码直接将一个耗时任务加入到了Event队列,这就直接导致写在前面的delayed任务在1秒后只能被加入到耗时任务之后,只有当前面耗时任务完成后,它才有机会得到执行。这种机制使得延迟任务变得不太可靠,你无法确定延迟任务到底在延迟多久之后被执行。
来源:CSDN
作者:阿拉阿伯
链接:https://blog.csdn.net/rd_w_csdn/article/details/103733505