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.pngIsolate相关类图
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技术。
网友评论