跟 Java 一样,具有唯一性,也就是从main()开始的线程。

微任务队列

里面包含众多微任务,主要是通过scheduleMicrotask进行调度。

事件任务队列

里面包含众多事件任务,例如:I/O 事件任务、Timer 事件任务等。

Dart 单线程优先级

主线程 > 微任务队列 > 事件任务队列。

所以,在 Dart 单线程中,会优先执行完主线程,在执行主线程的过程中,若发现微任务或者事件任务,就会将他们放入相应的任务队列中,然后就会一个个执行完微任务队列里面的微任务,其次再去执行事件任务队列里面的事件任务。

但是,会有特殊情况,那就是可以在微任务里面产生事件任务,而在事件任务中也能产生微任务,那么在这种情况下,他们是怎么执行的?

微任务产生事件任务

刚刚说到,在执行完主线程后才会执行微任务队列,但是,在执行微任务的时候产生了事件任务,这时就会把事件任务加入到事件任务队列中,由于微任务队列的优先级比事件任务的高,所以,依旧会先执行完微任务队列再执行事件任务队列。

事件任务产生微任务

由于微任务队列的优先级比事件任务队列的高,所以在执行到事件任务队列的时候,微任务队列已经为空了,但是在事件任务队列中产生了微任务,所以,在每次执行完当前的事件任务的时候,都会去判断微任务队列是否为空:

  • 微任务队列为空,继续执行下一个事件任务。
  • 微任务队列不为空,转而执行微任务,微任务完成后,再次判断微任务队列是否为空,不为空才执行事件任务队列。

代码验证

特别说明

由于代码时直接运行在 flutter 项目中,所以在贴代码的时候会删除

  • import 'package:flutter/material.dart';
  • runApp(MyApp());相关代码。

只保留核心代码。

基础代码示例

首先,我们先演示最简洁的示例,也就是只有一个主线程、一个微任务、一个事件任务。

import 'dart:async';

//主线程
void main() {
  print('main start!');
  //微任务
  scheduleMicrotask((){
    print('微任务执行!');
  });
  //事件任务
  Timer.run(() {
    print('事件任务执行!');
  });
  print('main end!');
}

运行结果:

I/flutter: main start!
 I/flutter: main end!
 I/flutter: 微任务执行!
 I/flutter: 事件任务执行!

延伸代码示例

下面演示的是在上面基础代码示例的基础上加上,微任务里面生成事件任务和在事件任务中生成微任务的情况。

import 'dart:async';

//主线程
void main() {
  print('main start!');
  //微任务
  scheduleMicrotask((){
    print('微任务 start!');
    //子事件任务
    Timer.run(() {
      print('子事件任务执行!');
    });
    print('微任务 end!');
  });
  //事件任务
  Timer.run(() {
    print('事件任务 start!');
    //子微任务
    scheduleMicrotask((){
      print('子微任务执行!');
    });
    print('事件任务 end!');
  });
  print('main end!');
}

运行结果:

I/flutter: main start!
 I/flutter: main end!
 I/flutter: 微任务 start!
 I/flutter: 微任务 end!
 I/flutter: 事件任务 start!
 I/flutter: 子微任务执行!
 I/flutter: 子事件任务执行!

阻塞问题