「这是我参加11月更文应战的第25天,活动概况检查:2021最后一次更文应战」

在之前的文章中,咱们已经学习了Future异步编程和Isolate线程的运用,今日咱们来看一下,怎么运用异步编程与多线程结合运用;

异步与多线程结合运用

咱们先来看一段代码:

void main() {
  testIsoLoad();
}
void testIsoLoad() {
  Future(() => compute(func, 123)).then((value) => print('1'));
  Future(() => compute(func, 123)).then((value) => print('2'));
  Future(() => compute(func, 123)).then((value) => print('3'));
  Future(() => compute(func, 123)).then((value) => print('4'));
  Future(() => compute(func, 123)).then((value) => print('5'));
}
func(int message) {}

运转工程,检查打印成果:

image.png

从打印成果咱们能够得到定论,这几个print操作时异步的,他是在子线程处理的;

可是依照咱们之前对Future的研讨,多个Future之间应该是同步的才对,那么为什么此处却变成了异步的呢?接下来,咱们在其他代码坚持不变的状况下,将testIsoLoad办法中的代码进行如下修正:

image.png

然后,咱们运转工程,看到一下打印成果:

image.png

正告咱们屡次运转项目,最后发现打印顺序都是1、2、3、4、5,那么这是为什么呢?怎样又变成了同步的呢?咱们仅仅只是将=>的调用方式换成了{},怎样代码的履行成果就不一样了呢?

需要注意的是,=>在调用的过程中,有将履行成果进行return操作的含义,也便是说=> compute(func, 123)的履行,会将compute(func, 123)的成果进行return操作,咱们来验证一下,将testIsoLoad办法修正如下:

image.png

运转成果如下:

image.png

屡次运转之后,发现成果并不是固定的,也便是说,咱们进行了return操作之后,同步的履行流程变成了异步的,这也验证了咱们上边所说的=>函数的调用方式会将成果进行return操作;

假如在Futurereturn了子线程的Future(compute是对Future的封装),那么其then将会处理子线程的异步使命;那么已然then是子线程的异步操作了,那么Future中的使命是什么状况呢?

咱们在Future中增加如下打印:

image.png

运转成果;

image.png

能够看到,尽管then处理的是子线程的异步使命,可是Future中仍然还是同步使命;

Future与微使命

咱们来看下边这样代码:

  Future f = Future(() {
    print('异步使命1');
    scheduleMicrotask(() {
      print('微使命1');
    });
  });

很明显,咱们都能才到履行成果是:异步使命先履行,然后履行微使命;

image.png

假如,咱们持续给f增加一个then办法呢?

  Future f = Future(() {
    print('异步使命1');
    scheduleMicrotask(() {
      print('微使命1');
    });
  });
  f.then((value) {
    print('微使命2');
  });

此时的履行成果怎么呢?

image.png

成果是微使命2微使命1先履行,这是由于then办法咱们能够看做和Future的使命是一个整体,也便是then办法(一个微使命)先增加进入队列,然后微使命1的微使命会增加到then办法后边,所以then办法先履行;

不仅仅如此,咱们再增加一个whenComplete办法检查打印成果:

  Future f = Future(() {
    print('异步使命1');
    scheduleMicrotask(() {
      print('微使命1');
    });
  });
  f.whenComplete(() {
    print('完成');
  });
  f.then((value) {
    print('微使命2');
  });

打印成果如下:

image.png

whenComplete也能够看做和Future的使命是一个整体,whenCompletethen会依照增加顺序履行;

异步与多线程的选择

那么究竟什么时分运用异步使命,什么时分运用多线程操作呢?

尽管Future是个异步使命,可是在Future中的耗时操作是会堵塞主线程的。看如下代码:

咱们在相机按钮的点击办法中增加了一个for循环来模拟耗时操作,能够从打印成果看到,当Future中的耗时操作开端履行之后,界面被堵塞,无法滑动!当耗时操作结束之后,才能进行滑动操作;

这个时分,咱们能够运用compute来操作:

将耗时操作放在compute的办法中,将不会堵塞主线程,此处能够直接运用compute,不必Future