Skip to content

源码:labs/dart/host/bin/runtime_concurrency/isolate_message_passing_demo.dart ​

  • 原始路径:labs/dart/host/bin/runtime_concurrency/isolate_message_passing_demo.dart
  • 类型:dart
dart
// Dart Isolate 消息传递:SendPort / ReceivePort 演示
//
// 对应 docs 01-runtime-concurrency/14-dart-isolate-message-passing.md:
// 1. Isolate.spawn + SendPort/ReceivePort:跨 isolate 单向传消息
// 2. 消息是深拷贝副本:isolate 之间不共享对象
// 3. 可传数据类型:基础类型 / List / Map / TransferableTypedData
// 4. 双向通信:两个 isolate 各持一个 port 对
//
// 运行:dart run bin/runtime_concurrency/isolate_message_passing_demo.dart

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

// 子 isolate 入口:接收主 isolate 发来的 SendPort 与数据
void childIsolate(SendPort mainPort) {
  // 子 isolate 再开一个 ReceivePort,把它的 SendPort 发回主 isolate → 双向
  final childReceivePort = ReceivePort();
  mainPort.send(childReceivePort.sendPort); // 1. 先回传自己的 port

  childReceivePort.listen((message) {
    if (message is List && message.isNotEmpty) {
      final type = message[0];
      if (type == 'echo') {
        // 回传"深拷贝证明":修改副本看主 isolate 是否受影响
        final data = (message[1] as List).cast<int>();
        data[0] = 999; // 修改"副本"
        mainPort.send(['echo_back', data, '我在子 isolate 改了这个 List 的首元素']);
      } else if (type == 'compute') {
        // 演示把 CPU 重活搬过来
        var sum = 0;
        for (var i = 0; i < (message[1] as int); i++) {
          sum += i;
        }
        mainPort.send(['result', sum]);
      }
    }
  });
}

Future<void> main() async {
  print('=== 1. 双向通信 + 深拷贝证明 ===');
  final receivePort = ReceivePort();
  await Isolate.spawn(childIsolate, receivePort.sendPort);

  // ReceivePort 是单订阅流,只能 listen 一次:握手与业务消息统一处理
  final childPortCompleter = Completer<SendPort>();
  final replies = <dynamic>[];
  receivePort.listen((message) {
    if (message is SendPort) {
      childPortCompleter.complete(message); // 1. 握手:拿到子 isolate 的 SendPort
    } else {
      replies.add(message); // 2. 业务回复
    }
  });

  final childPort = await childPortCompleter.future;

  // 传 List:子 isolate 会拿到一份深拷贝副本
  final myList = [1, 2, 3, 4];
  childPort.send(['echo', myList]);
  // 同时发一个计算任务
  childPort.send(['compute', 1000000]);

  // 等两条回复处理完
  await Future.delayed(const Duration(milliseconds: 500));
  for (final reply in replies) {
    if (reply[0] == 'echo_back') {
      print('  回传数据: ${reply[1]}');
      print('  证明深拷贝: 我主 isolate 的 myList 还是 $myList(未被子 isolate 改动)');
      print('  子 isolate 说明: ${reply[2]}');
    } else if (reply[0] == 'result') {
      print('  子 isolate 计算结果: sum(0..999999) = ${reply[1]}');
    }
  }

  // 用 TransferableTypedData 传大数据(零拷贝转移所有权)
  print('');
  print('=== 2. TransferableTypedData:大数据零拷贝转移 ===');
  final bytes = Uint8List.fromList(List.generate(100, (i) => i % 256));
  final transferable = TransferableTypedData.fromList([bytes]);
  print('  转移前 buffer 可用: ${bytes.isNotEmpty}');
  // transfer 后原 buffer 被 detach;接收端 materialize 取回
  final received = transferable.materialize().asUint8List();
  print('  接收端 materialize 拿到 ${received.length} 字节');

  print('');
  print('=== 3. 结论 ===');
  print('  isolate 之间:不共享堆、消息深拷贝(或 TransferableTypedData 转移所有权)');
  print('  数据竞争不存在,代价是传递成本;重计算应整体搬到子 isolate 而非传大数据');
}

站点构建时间:2026/8/24 23:43:17