阅读 956

Dart单线程理解(与Java完全不同) | 创作者训练营第二期

Dart 单线程说明

在 Java 中,默认为单线程执行,也就是通过main()方法进行执行,按照顺序执行方式运行代码。

而 Dart 的单线程跟 Java 的完全不同,虽然都是单线程,但是 Dart 分为三个形式:

  • 主线程
  • 微任务队列
  • 事件任务队列

主线程

跟 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: 子事件任务执行!
复制代码

阻塞问题

虽然按照上面的结果可以看出在单线程中,主线程、微任务队列、事件任务队列都是线性运行的,那么,假如我们在他们里面加入了阻塞操作,会不会依旧为线性运行?还是说,其实任务队列是并发的,只是微任务队列的优先级比事件任务队列的优先级高一点而已。

这里,我们通过加入sleep(Duration(seconds: 2));代码模拟耗时操作。

import 'dart:async';
import 'dart:io';

//主线程
void main() {
  print('main start!');
  sleep(Duration(seconds: 2));
  //微任务
  scheduleMicrotask((){
    print('微任务 start!');
    sleep(Duration(seconds: 2));
    //子事件任务
    Timer.run(() {
      print('子事件任务执行!');
      sleep(Duration(seconds: 2));
    });
    print('微任务 end!');
  });
  //事件任务
  Timer.run(() {
    print('事件任务 start!');
    sleep(Duration(seconds: 2));
    //子微任务
    scheduleMicrotask((){
      print('子微任务执行!');
      sleep(Duration(seconds: 2));
    });
    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: 子事件任务执行!
复制代码

结果依旧一样,说明在 Dart 单线程中,主线程、微任务队列、事件任务队列是线性执行的!

猜你喜欢

创作不易,你的点赞是我最大的支持。

文章分类
Android
文章标签