Flutter学习-22- Dart中的多线程

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

我们之前学习了dart中的异步编程,但是Dart是个单线程开发,这里的异步编程和我们iOS中的异步多线程不一样,dart中有类似的多线程,接下来我们就来了解下。

1. Isolate

先看一个例子

void IsolateTest(){

  print('A');
  Future(()=>print('B'));
  sleep(Duration(seconds: 1));
  print('C');
}
复制代码

按照我们iOS中的想法主线程堵塞异步子线程会执行从而打印ABC,但是在Future中是单线程,就一个线程异步只是加入了任务队列,主线程堵塞,队列的任务也不会执行,所以最后是ACB

void IsolateTest(){

  print('A');
  Isolate.spawn(func,10);
  sleep(Duration(seconds: 1));
  print('C');
}

func(int num)=>print('B');
复制代码

我们使用Isolate进行异步操作,并传入一个值,打印结果是ABC,是我们想要的结果

image.png

我们在来验证下我们理解的多线程

void IsolateTest(){

  print('A');
  Isolate.spawn(func,10);
  Isolate.spawn(func2,10);
  Isolate.spawn(func,10);
  Isolate.spawn(func2,10);
  Isolate.spawn(func,10);
  Isolate.spawn(func2,10);
  Isolate.spawn(func,10);
  Isolate.spawn(func2,10);
  sleep(Duration(seconds: 3));
  print('C');
}

func(int num)=>print('B1');
func2(int num)=>print('B2');
复制代码

按照我们之前的理解,应该是A之后是B1B2B1B2这样的添加顺序,实际打印的是随机的,不是同步的

image.png 这就类似我们iOS中的子线程了,但是实际上并不是完全一样,我们在外部定义一个变量,之后Isolate线程中改变它的值,之后主线程再打印。

void IsolateTest(){

  print('A');
  Isolate.spawn(func,10);
  sleep(Duration(seconds: 3));
  print('a= $a');
  print('C');
}
int a = 1;
func(int num) {
  a =num;
  print('a= $a');
}
复制代码

image.png Isolate更像一个进程,意味着它有单独的内存空间,不会抢夺资源,所以我们就不需要加锁处理。但是我们想要改变值的话该怎么做呢,继续往下看


void IsolateTest(){

  print('A');

  //创建一个prot
  ReceivePort port = ReceivePort();

  Isolate.spawn(func,port.sendPort);//传递


  port.listen((message) { //监听
    a = message;
    print(message);
  });
  
  // sleep(Duration(seconds: 1));
  print('a= $a');
  print('C');
}
int a = 1;
//方法使用SendPort接受
func(SendPort sendPort) {
  sendPort.send(101);//发送消息
  a = 101;
  print('a= $a');
}
复制代码

我们使用ReceivePort来传递值,port.listen来监听值的改变,我们主线程在做出对应的改变,我们使用完成后要手动的关闭

Future<void> IsolateTest() async {

  print('A');

  //创建一个prot
  ReceivePort port = ReceivePort();

 Isolate iso = await Isolate.spawn(func,port.sendPort);//传递


  port.listen((message) { //监听
    a = message;
    print(message);
    port.close();
    iso.kill();
  });

  sleep(Duration(seconds: 3));
  print('a= $a');
  print('C');
}
复制代码

我们使用await 拿到iso 之后接受到了关闭端口,之后杀掉线程iso.kill

2. compute

compute是Isolate的封装,使用方法类似。 image.png

computeTest(){

  print('A');
  compute(func2,10);
  sleep(Duration(seconds: 2));
  print('C');
}

func2(int num){
  print('子线程来了');
}
复制代码

打印结果:

image.png 我们想要改变内部的值的话,我们使用await接收

int a = 1;
computeTest() async{

  print('A');
  a = await compute(func2,10);
  sleep(Duration(seconds: 2));
  print('C');
  print('a = $a');
}

int func2(int num){
  print('子线程来了');
  return 100;
}
复制代码

打印结果为:

image.png

我们在子线程内部改变变量,外部打印下没有改变,其本质和我们Isolate一样。

image.png

另外compute不需要我们手动关闭

猜你喜欢

转载自juejin.im/post/7032648508247441421