Dart是单线程的,这个线程有自己可以访问的内存空间以及需要运行的事件循环;
我们可以将这个空间系统称之为是一个Isolate;
比如Flutter中就有一个Root Isolate,负责运行Flutter的代码,比如UI渲染、用户交互等等;

在 Isolate 中,资源隔离做得非常好,每个 Isolate 都有自己的 Event Loop 与 Queue,Isolate 之间不共享任何资源,只能依靠消息机制通信,因此也就没有资源抢占问题。

但是,如果只有一个Isolate,那么意味着我们只能永远利用一个线程,这对于多核CPU来说,是一种资源的浪费。
如果在开发中,我们有非常多耗时的计算,完全可以自己创建Isolate,在独立的Isolate中完成想要的计算操作。

1 创建一个Isolate

Isolate.spawn可以创建一个Isolate

  1. import "dart:isolate";
  2. main(List<String> args) {
  3. Isolate.spawn(foo, "Hello Isolate");
  4. }
  5. void foo(info) {
  6. print("新的isolate:$info");
  7. }

2 Isolate通信机制

但是在真实开发中,我们不会只是简单的开启一个新的Isolate,而不关心它的运行结果:

  • 我们需要新的Isolate进行计算,并且将计算结果告知Main Isolate(也就是默认开启的Isolate);
  • Isolate 通过发送管道(SendPort)实现消息通信机制;
  • 我们可以在启动并发Isolate时将Main Isolate的发送管道作为参数传递给它;

并发在执行完毕时,可以利用这个管道给Main Isolate发送消息;

  1. import "dart:isolate";
  2. main(List<String> args) async {
  3. // 1.创建管道
  4. ReceivePort receivePort= ReceivePort();
  5. // 2.创建新的Isolate
  6. Isolate isolate = await Isolate.spawn<SendPort>(foo, receivePort.sendPort);
  7. // 3.监听管道消息
  8. receivePort.listen((data) {
  9. print('Data:$data');
  10. // 不再使用时,我们会关闭管道
  11. receivePort.close();
  12. // 需要将isolate杀死
  13. isolate?.kill(priority: Isolate.immediate);
  14. });
  15. }
  16. void foo(SendPort sendPort) {
  17. sendPort.send("Hello World");
  18. }

但是我们上面的通信变成了单向通信,如果需要双向通信呢?
事实上双向通信的代码会比较麻烦;

  • Flutter提供了支持并发计算的compute函数,它内部封装了Isolate的创建和双向通信;
  • 利用它我们可以充分利用多核心CPU,并且使用起来也非常简单;

注意:下面的代码不是dart的API,而是Flutter的API,所以只有在Flutter项目中才能运行

  1. main(List<String> args) async {
  2. int result = await compute(powerNum, 5);
  3. print(result);
  4. }
  5. int powerNum(int num) {
  6. return num * num;
  7. }