Dart 单线程模型
Java和OC都是多线程模型的编程语言,任意一个线程触发异常且该异常未被捕获时,就会导致整个进程退出。但Dart和JavaScript不会,它们都是单线程模型,运行机制很相似(但有区别)。
Dart在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另一个叫做“事件队列” event queue。微任务队列的执行优先级高于事件队列。
Dart大致运行原理:先开启app执行入口函数main(),执行完成之后,消息机制启动,先是会按照先进先出的顺序逐个执行微任务队列中的任务microtask,事件任务eventtask执行完毕后便会退出,但是,在事件任务执行的过程中也可以插入新的微任务和事件任务,在这种情况下,整个线程的执行过程便是一直在循环,不会退出,而Flutter中,主线程的执行过程正是如此,永不终止。
在事件循环中,当某个任务发生异常并没有被捕获时,程序并不会退出,而直接导致的结果是当前任务的后续代码就不会被执行了,也就是说一个任务中的异常是不会影响其它任务执行的。
Dart 中事件的执行顺序:Main > MicroTask > EventQueue
通常使用 scheduleMicrotask(…)或者Future.microtask(…)方法向微任务队列插入一个任务。
通常使用 Future 向 EventQueue加入事件,也可以使用 async 和 await 向 EventQueue 加入事件。
例如:
void run(){ Future(() async { print("EvenTask1"); }); evenTest(); Future(() async{ print("EvenTask2"); await Future((){ print("EvenTask4"); }); print("EvenTask3"); }); Future.microtask(() => print("MicroTask1")); scheduleMicrotask((){ print("MicroTask2"); }); print("main"); } void evenTest() async{ await Future((){ print("EvenTask5"); }); }
输出结果是:
在Dart中,所有的外部事件任务都在事件队列中,如IO、计时器、点击、以及绘制事件等,而微任务通常来源于Dart内部,并且微任务非常少,之所以如此,是因为微任务队列优先级高,如果微任务太多,执行时间总和就越久,事件队列任务的延迟也就越久,对于GUI应用来说最直观的表现就是比较卡,所以必须得保证微任务队列不会太长。
参考文档:
https://book.flutterchina.club/chapter2/thread_model_and_error_report.html
https://juejin.cn/post/6844903816618311688