- 1:Isolate
- 1.1:使用Isolate
- 2:事件循环
尽管Dart是单线程语言,但它支持Future、Stream等其他内容。 本文介绍了Dart支持后台工作的基础:Isolate和事件循环。
Isolate
所有Dart代码都在isolate中运行程序。它就像是机器上的一个小空间,具有自己的私有内存块和一个运行事件循环的单个线程。
隔离区具有自己的内存和运行事件循环的单个执行线程
在许多其他语言(例如C ++)中,可以让多个线程共享同一内存并运行所需的任何代码。 但是,在Dart中,每个线程都与自己的内存处于隔离状态。
许多Dart应用程序都在单个隔离区(isolate)中运行所有代码,但是如果需要,可以同时拥有多个隔离区(isolate)。 如果要执行的计算量非常大,以至于如果它在主隔离区中运行,可能会导致丢帧,那么可以使用Isolate.spawn()或Flutter的compute()函数。 这两个函数都创建了一个单独的隔离区(isolate)来进行数字运算,使主隔离区程序可以自由地重建和呈现小部件树。
两个隔离区,每个隔离区都有自己的内存和线程
新隔离区具有自己的事件循环和内存,即使原始隔离区是该新隔离区的父级,也不允许其访问。
实际上,隔离区之间一起工作的唯一方法是通过来回传递消息。 一个隔离区向另一个发送消息,接收隔离区使用其事件循环来处理该消息。
缺少共享内存听起来可能会很严格,尤其是如果之前使用的是Java或C ++之类的语言时,但这对Dart编码人员来说有一些关键的好处。
例如,隔离区中的内存分配和垃圾回收不需要锁。 这对于Flutter应用程序效果很好,例如有时需要快速构建和移除一堆小部件。
使用Isolate
要使用隔离区来进行并发编程:
import 'dart:isolate';
该library主要包含下面几个类:
1、 Capability:当通过其他隔离区时返回相同一个不可伪造的对象。
2、 Isolate:Dart执行上下文的隔离区。
3、 RawReceivePort:
4、 ReceivePort:与SendPort一起,是隔离区之间唯一的通信方式。
5、 SendPort:将消息发送到其ReceivePorts。
要创建Isolate,可以使用spawn方法。而且必须为spawn方法提供一个带有单个参数[SendPort]的方法。 通常,此参数表示隔离应用于发送回通知消息的端口:
Isolate isolate;
void start() async {
ReceivePort receivePort= ReceivePort(); //port for this main isolate to receive messages.
isolate = await Isolate.spawn(runTimer, receivePort.sendPort);
receivePort.listen((data) {
stdout.write('RECEIVE: ' + data + ', ');
});
}
void runTimer(SendPort sendPort) {
int counter = 0;
Timer.periodic(new Duration(seconds: 1), (Timer t) {
counter++;
String msg = 'notification ' + counter.toString();
stdout.write('SEND: ' + msg + ' - ');
sendPort.send(msg);
});
}
void stop(){
print("kill isolate");
isolate?.kill(priority: Isolate.immediate);
isolate =null;
}
事件循环
当应用程序启动,到应用程序停止,会发生一系列事件:来自磁盘的I/O,来自用户的手指点击……各种各样的东西。应用无法预测这些事件何时发生或以什么顺序发生,因此必须使用一个永不阻塞的线程来处理所有这些事件。 因此,应用运行一个事件循环。 它从事件队列中获取最先提交的的事件来进行处理,返回到下一个事件,进行处理,依此类推,直到事件队列为空。
事件循环一次处理一个事件
当事件执行完成时,线程会挂起,等待下一个事件。 它可以触发垃圾回收等等。
Dart用于异步编程的所有高级API和语言功能(Future、Steam、async、await)都基于此事件循环而构建。