Dart 多线程:Isolate
Dart 被设计成为单线程、异步的语言。 尤其在 Flutter 当中,大部分的 Dart 代码都执行在一个线程,应该叫一个 Isolate 里面。
单线程带来了很多好处,不用考虑数据被同时访问,不用加锁,也就有没有了死锁;也给内存的垃圾回收带来了方便。
Isolate 对象 Link to heading
- Isolate 代表了 Dart 执行的上下文,所有的 Dart 代码都运行在其中。
- Dart 代码只能访问到当前 Isolate 的类和变量,不同 Isolate 之间内存是隔离的,只能通过 Ports 进行通讯。
- 每一个 Isolate 都有独立的消息循环和垃圾回收。
- Isolate 可以被其他的 Isolate 控制,比如暂停,终止等。 这些操作都比较危险,可以做访问控制。
- Isolate 对象不能在多个 Isolate 之间进行传递,但是 SendPort 对象和 Capability 对象可以传递。
Port 对象 (ReceivePort, RawRecivePort, SendPort) Link to heading
- Port 是多个 Isolate 之间通讯的管道,是单向的。
- ReceivePort 和 SendPort 是成对使用的,SendPort 是由 ReceivePort 创建的,通过 ReceivePort 对象或 RawRecivePort 对象的 sendPort 成员获取。
- ReceivePort 是一个 Stream, 可以直接监听。
- RawReceivePort 比较底层,需要设置处理函数 handler 来接收消息; handler 的调用没有 Zone 的概念,所以永远在 Zone.root 里面。
Capability 对象 Link to heading
- Capability 对象是可以在多个 Isolate 之间传递的对象,因为内存是隔离的,理论上不同的 Isolate 里面是不可能有相同对象的,Capablility 对象是专门实现的一种特殊对象,在不同 Isolate 传递时,还能保持相等。
- Capability 对象可以作为凭据在 Isolate 间对 Isolate 的操作做访问控制。
代码示例 Link to heading
import 'dart:async';
import 'dart:isolate';
main() async {
var receivePort = new ReceivePort();
await Isolate.spawn(echo, receivePort.sendPort);
// The 'echo' isolate sends it's SendPort as the first message
var sendPort = await receivePort.first;
var msg = await sendReceive(sendPort, "foo");
print('received $msg');
msg = await sendReceive(sendPort, "bar");
print('received $msg');
}
// the entry point for the isolate
echo(SendPort sendPort) async {
// Open the ReceivePort for incoming messages.
var port = new ReceivePort();
// Notify any other isolates what port this isolate listens to.
sendPort.send(port.sendPort);
await for (var msg in port) {
var data = msg[0];
SendPort replyTo = msg[1];
replyTo.send(data);
if (data == "bar") port.close();
}
}
/// sends a message on a port, receives the response,
/// and returns the message
Future sendReceive(SendPort port, msg) {
ReceivePort response = new ReceivePort();
port.send([msg, response.sendPort]);
return response.first;
}