flutter isolate microTask

2023-02-16 10:11:26 浏览数 (2)

Isolate 线程(进程)

isolate开辟的线程是随机并发的

代码语言:javascript复制
isolateDemo() {
  Isolate.spawn(func1, 10);
  Isolate.spawn(func2, 10);
  Isolate.spawn(func1, 10);
  Isolate.spawn(func2, 10);
  Isolate.spawn(func1, 10);
  Isolate.spawn(func2, 10);
}

func1(int num) {
  print('任务1');
}
func2(int num) {
  print('任务2');
}

输入结果:
I/flutter ( 1559): 任务1
I/flutter ( 1559): 任务2
I/flutter ( 1559): 任务2
I/flutter ( 1559): 任务1
I/flutter ( 1559): 任务1
I/flutter ( 1559): 任务2

isolate开辟的线程是在新的进程上开辟的,拥有完全独立的内存空间

代码语言:javascript复制
int count = 10;
isolateDemo() {
  Isolate.spawn(func, 100);
  sleep(const Duration(seconds: 5));//睡眠5s,等待子线程执行完
  print('count = $count');
}

func(int num) {
  count = num;
  print('isolate.count = $count');
}

I/flutter ( 1559): isolate.count = 100
I/flutter ( 1559): count = 10

从结果上看,子线程修改完全局变量,主线程的count还是原来的值。要想从子线程同步执行结果,dart提供了接口port,监听port回调来获得子线程的回调结果。

代码语言:javascript复制
int count = 10;
isolateDemo() async{
  ReceivePort receive = ReceivePort();
  Isolate iso = await Isolate.spawn(func, receive.sendPort);
  receive.listen((message) {
      count = message;
      print('接收到 新的count = $count');
      receive.close();//用完需关闭port
      iso.kill();
  });
  sleep(const Duration(seconds: 5));
  print('count = $count');
}

func(SendPort sendPort) {
  count = 100;
  sendPort.send(count);
  print('isolate.count = $count');
}

I/flutter ( 1559): isolate.count = 100
I/flutter ( 1559): count = 10
I/flutter ( 1559): 接收到 新的count = 100

compute 与 isolate的区别,compute是是在isolate的上再封装了一层。compute有返回值直接就可以接受。

代码语言:javascript复制
const ComputeImpl compute = isolates.compute;
代码语言:javascript复制
computeDemo() async{
  print('代码1');
  int num = await compute(func3,100) as int;
  print('num = $num');
  print('代码2');
}

int func3(int count){
  sleep(Duration(seconds: 5));
  return 1000;
}

I/flutter ( 1559): 外部代码1
I/flutter ( 1559): num= 1000
I/flutter ( 1559): 外部代码2

而且,await会堵塞下面的代码,直到compute执行完才继续往下执行。如果是isolate.spawn直接开辟的线程是不会堵塞往下的代码。

无论是compute 还是 isolate都必须在asyn函数内使用。

事件任务与微任务

在每一次事件循环中,Dart总是先去第一个microtask queue中查询是否有可执行的任务,如果没有,才会处理后续的event queue的流程

task run looptask run loop
代码语言:javascript复制
void futureDemo(){
  Future f1 = Future(() => null);

  Future f2 = Future(() => debugPrint('1'));
  f2.then((value) => debugPrint('4'));

  f1.then((value) {
    debugPrint('6');
  }).then((value) => debugPrint('8'));

  Future(() => debugPrint('2'));
  scheduleMicrotask(() {debugPrint('3');});
  debugPrint('5');
  //5 3 6 1 4 2
}

结果:
I/flutter ( 1559): 5
I/flutter ( 1559): 3
I/flutter ( 1559): 6
I/flutter ( 1559): 8
I/flutter ( 1559): 1
I/flutter ( 1559): 4
I/flutter ( 1559): 2

代码段执行顺序:主线程 - 队列(Future) - 微任务(scheduleMicrotask)

future和then分开写还是一起写,都是同一行执行语句。future执行完,马上就会执行相应的then、whenComplete

代码语言:javascript复制
void futureDemo(){
  Future f1 = Future(() => null);
  f1.then((value) {
    debugPrint('6');
    scheduleMicrotask(() {debugPrint('7');});//f1、then、whenComplete同属一执行语句。每个事件任务执行完会再去轮询微任务
  }).then((value) => debugPrint('8')).whenComplete(() => debugPrint('9'));

  Future f2 = Future(() => debugPrint('1'));
  f2.then((value) => debugPrint('4'));

  Future(() => debugPrint('2'));
  scheduleMicrotask(() {debugPrint('3');});//微任务
  debugPrint('5');
  //5 3 6 8 9 7 6 1 4 2
}

I/flutter ( 1559): 5
I/flutter ( 1559): 3
I/flutter ( 1559): 6
I/flutter ( 1559): 8
I/flutter ( 1559): 9
I/flutter ( 1559): 7
I/flutter ( 1559): 1

0 人点赞