美文网首页Android进阶之路Android技术知识
Flutter启动流程(Isolate机制+创建流程+线程练习)

Flutter启动流程(Isolate机制+创建流程+线程练习)

作者: 码农的地中海 | 来源:发表于2022-07-18 22:26 被阅读0次

Flutter是使用Dart语言为基础的,所以它的线程机制使用的也是Dart的线程机制。Dart 是单线程,Dart 为我们提供了 isolate,isolate 跟线程差不多,它可以理解为 Dart 中的线程。isolate 与线程的区别就是线程与线程之间是共享内存的,而 isolate 和 isolate 之间是不共享的,所以叫 isolate (隔离)。

isolate定义

isolate是Dart对actor并发模式的实现。运行中的Dart程序由一个或多个actor组成,这些actor也就是Dart概念里面的isolate。isolate是有自己的内存和单线程控制的运行实体。isolate本身的意思是“隔离”,因为isolate之间的内存在逻辑上是隔离的。isolate中的代码是按顺序执行的,任何Dart程序的并发都是运行多个isolate的结果。因为Dart没有共享内存的并发,没有竞争的可能性所以不需要锁,也就不用担心死锁的问题。

由于isolate之间没有共享内存,所以他们之间的通信唯一方式只能是通过Port进行,而且Dart中的消息传递总是异步的。

isolate机制

Dart是基于单线程模型的语言。但是在开发当中我们经常会进行耗时操作比如网络请求,这种耗时操作会堵塞我们的代码,所以在Dart也有并发机制,名叫isolate。APP的启动入口main函数就是一个类似Android主线程的一个主isolate。和Java的Thread不同的是,Dart中的isolate无法共享内存。

资料获取:【戳我获取】实战混合式开发Flutter3.0手册

Isolate创建流程图

image.png

Isolate相关类图

image.png

对于Root Isolate来说,RuntimeController初始化过程会创建该Isolate对象,在该对象析构时会关闭该isolate对象;

  • 创建Isolate对象:dart_api_impl.cc中的Dart_CreateIsolate,会调用到dart.cc的CreateIsolate()
  • 关闭Isolate对象:dart_api_impl.cc中的Dart_ShutdownIsolate,会调用到dart.cc的ShutdownIsolate()

isolate之间的通信

由于isolate之间没有共享内存,所以他们之间的通信唯一方式只能是通过Port进行,而且Dart中的消息传递总是异步的。

isolate与普通线程的区别

我们可以看到isolate神似Thread,但实际上两者有本质的区别。操作系统内内的线程之间是可以有共享内存的而isolate没有,这是最为关键的区别。

isolate实现简述

我们可以阅读Dart源码里面的isolate.cc文件看看isolate的具体实现。
我们可以看到在isolate创建的时候有以下几个主要步骤:

  • 初始化isolate数据结构
  • 初始化堆内存(Heap)
  • 进入新创建的isolate,使用跟isolate一对一的线程运行isolate
  • 配置Port
  • 配置消息处理机制(Message Handler)
  • 配置Debugger,如果有必要的话
  • 将isolate注册到全局监控器(Monitor)

我们看看isolate开始运行的主要代码

Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) {
  // Schedule the thread into the isolate by associating
  // a 'Thread' structure with it (this is done while we are holding
  // the thread registry lock).
  Thread* thread = NULL;
  OSThread* os_thread = OSThread::Current();
  if (os_thread != NULL) {

    MonitorLocker ml(threads_lock(), false);

    // Check to make sure we don't already have a mutator thread.
    if (is_mutator && scheduled_mutator_thread_ != NULL) {
      return NULL;
    }

   
    while (!bypass_safepoint && safepoint_handler()->SafepointInProgress()) {
      ml.Wait();
    }

    // Now get a free Thread structure.
    thread = thread_registry()->GetFreeThreadLocked(this, is_mutator);
    ASSERT(thread != NULL);

    // Set up other values and set the TLS value.
    thread->isolate_ = this;
    ASSERT(heap() != NULL);
    thread->heap_ = heap();
    thread->set_os_thread(os_thread);
    ASSERT(thread->execution_state() == Thread::kThreadInNative);
    thread->set_execution_state(Thread::kThreadInVM);
    thread->set_safepoint_state(0);
    thread->set_vm_tag(VMTag::kVMTagId);
    ASSERT(thread->no_safepoint_scope_depth() == 0);
    os_thread->set_thread(thread);
    if (is_mutator) {
      scheduled_mutator_thread_ = thread;
      if (this != Dart::vm_isolate()) {
        scheduled_mutator_thread_->set_top(heap()->new_space()->top());
        scheduled_mutator_thread_->set_end(heap()->new_space()->end());
      }
    }
    Thread::SetCurrent(thread);
    os_thread->EnableThreadInterrupts();

    thread->ResetHighWatermark();
  }
  return thread;
}

我们可以看到Dart本身抽象了isolate和thread,实际上底层还是使用操作系统的提供的OSThread。


image.png

练习 Isolate

Dart 提供了 isolate, isolate与线程类似,isolate与线程的区别是 :线程与线程之间是共享内存的,而isolate与isolate之间是不共享内存的。
async/await Future 也可实现异步操作,这种异步其实是运行在同一线程中并没有开启新的线程, 只是通过单线程的任务调度实现一个先执行其他的代码片段,等这边有结果后再返回的异步效果。

演示代码

import 'dart:async';
import 'dart:isolate';

void main(List<String> arguments) {
  isolateTest();
}

//异步调度

void doWork(List list) {
  SendPort sendPort = list[0];
  print('--------------异步调度开始');
  ReceivePort receivePort = ReceivePort();
  SendPort sp = receivePort.sendPort;
  //传递给主线 发送对象,达到双向通信
  sendPort.send(sp);
  //监听对象
  StreamSubscription streamSubscription;

  streamSubscription = receivePort.listen((message) {
    print('--------------异步接收到消息 $message');
    if (message == -1) {
      print('--------------异步接收到-1 结束通信');
      streamSubscription?.cancel();
      return;
    }
    sendPort.send(message + 1);
  });
}

///Isolate调度测试
void isolateTest() async {
  //接收
  ReceivePort receivePort = ReceivePort();
  //发送
  SendPort sendPort = receivePort.sendPort;

  //调用异步
  Isolate isolate = await Isolate.spawn(doWork, [sendPort, '传递参数']);
  //异步发送对象
  SendPort workSendProt;

  //监听对象
  StreamSubscription streamSubscription;
  streamSubscription = receivePort.listen((message) {
    if (message is SendPort) {
      workSendProt = message;
      print('接收到异步发来的 sendProt');
      //开始通信
      workSendProt.send(1);
      return;
    }
    print('异步调度发来消息: $message');
    if (message >= 20) {
      //结束通信
      print('发起结束通信');
      workSendProt.send(-1);
      streamSubscription?.cancel();
      isolate.kill();
      return;
    }
    workSendProt.send(message + 1);
  });
}

运行结果

--------------异步调度开始
接收到异步发来的 sendProt
--------------异步接收到消息 1
异步调度发来消息: 2
--------------异步接收到消息 3
异步调度发来消息: 4
--------------异步接收到消息 5
异步调度发来消息: 6
--------------异步接收到消息 7
异步调度发来消息: 8
--------------异步接收到消息 9
异步调度发来消息: 10
--------------异步接收到消息 11
异步调度发来消息: 12
--------------异步接收到消息 13
异步调度发来消息: 14
--------------异步接收到消息 15
异步调度发来消息: 16
--------------异步接收到消息 17
异步调度发来消息: 18
--------------异步接收到消息 19
异步调度发来消息: 20
发起结束通信
--------------异步接收到消息 -1
--------------异步接收到-1 结束通信

Process finished with exit code 0

资料展现【一键获取】【戳我获取】实战混合式开发Flutter3.0手册

03编写实战一个Flutter APP .png 01Flutter特性.png 02在windows上搭建Flutter开发环境.png

资料获取:【戳我获取】实战混合式开发Flutter3.0手册

总结

Flutter层面的线程配置管理以及Dart本身isolate的实现。在深入了解Flutter线程机制以后,我们在开发过程当中更加得心应手,同时也启发我们如何去设计类似应用内的线程结构。

本文讲解了简单的isolate的创建流程;isolate机制浅析与简单的练习。可以点赞关注后续的更多Android技术。

相关文章

网友评论

    本文标题:Flutter启动流程(Isolate机制+创建流程+线程练习)

    本文链接:https://www.haomeiwen.com/subject/kbadirtx.html