【问题标题】:Flutter Isolate vs FutureFlutter 隔离与未来
【发布时间】:2019-03-01 02:42:30
【问题描述】:

我可能对孤立和未来有错误的想法。请帮我清理一下。这是我对这两个主题的理解。

Isolate:Isolates 在自己的事件循环中运行代码,每个事件可能会在嵌套的微任务队列中运行较小的任务。

Future:Future 用于表示将来某个时间可用的潜在值或错误。

我的困惑是:

  1. 文档说 Isolate 有它自己的循环?我觉得拥有自己的事件队列对我来说更有意义,我错了吗?

  2. 未来是否在主 Isolate 上异步运行?我假设未来的任务实际上被放置在事件队列的末尾,所以如果它将来会被循环执行。如果我错了,请纠正我。

  3. 既然有未来,为什么还要使用 Isolate?我看到了一些使用 Isolate 代替 Future 来完成繁重任务的示例。但为什么?只有当将来在主隔离队列上异步执行时,它才对我有意义。

【问题讨论】:

  • 隔离就像线程。期货不是。因此,如果您有昂贵的计算,Future 仍会阻塞 UI,但 Isolate 不会。

标签: dart flutter future dart-isolates


【解决方案1】:

Future 是一个句柄,可让您在异步执行完成时收到通知。 异步执行使用事件队列,代码在同一个线程内并发执行。

https://webdev.dartlang.org/articles/performance/event-loop

Dart 代码默认在根隔离中执行。

您可以启动通常在另一个线程上运行的其他隔离。 隔离可以从与根隔离开始时使用的相同 Dart 代码(与 main() https://api.dartlang.org/stable/2.0.0/dart-isolate/Isolate/spawn.html 不同的入口点)或不同的 Dart 代码(从某个 Dart 文件或 URL https://api.dartlang.org/stable/2.0.0/dart-isolate/Isolate/spawnUri.html 加载)加载。

隔离不共享任何状态,只能使用消息传递(SendPort/ReceivePort)进行通信。每个隔离区都有自己的事件队列。

https://webdev.dartlang.org/articles/performance/event-loop

【讨论】:

  • dart 是否允许我们像 Java 一样拥有主线程和后台线程?
  • Dart 中没有真正的线程。隔离在不同的操作系统线程上运行,但它们与 Java 线程有很大不同(无共享状态)。
  • 是的,正如我在第一段中解释的那样。代码是单线程执行的(没有额外的隔离),同步代码总是在执行另一个回调之前运行到最后。
  • 当你说isolates运行在不同的OS线程上,是否意味着每个isolates都有自己的事件循环、事件队列和微任务队列?
  • 是的,我的回答中也提到了。
【解决方案2】:

Isolate 在单个线程上运行 Dart 代码。像

这样的同步代码
print('hello');

立即运行,不可中断。

Isolate 还有一个事件循环,用于安排异步任务。异步并不意味着这些任务在单独的线程上运行。它们仍然在同一个线程上运行。异步只是意味着它们被安排在以后。

事件循环运行在所谓的事件队列中安排的任务。您可以通过创建这样的未来将任务放入事件队列中:

Future(() => print(hello));

print(hello) 任务将在事件队列中前面的其他任务完成后运行。所有这些都发生在同一个线程上,即同一个 Isolate。

例如,某些任务不会立即添加到事件队列中

Future.delayed(Duration(seconds: 1), () => print('hello'));

延迟一秒后才被添加到队列中。

到目前为止,我一直在谈论的所有内容都是在同一个线程上完成的,同一个 Isolate。不过,有些工作实际上可能在不同的线程上完成,例如 IO 操作。底层框架负责这一点。如果在主 Isolate 线程上完成了诸如从磁盘读取之类的昂贵操作,那么它将阻塞应用程序直到完成。当 IO 操作完成时,future 完成并将结果更新添加到事件队列中。

当您需要自己执行 CPU 密集型操作时,您应该在另一个隔离区上运行它们,这样它就不会导致您的应用出现卡顿。 compute 属性对此很有用。您仍然使用未来,但这次未来将返回来自不同 Isolate 的结果。

进一步研究

【讨论】:

  • 可以从没有 ReceivePort 和 SendPort 的隔离中检索数据吗?例如,将获得的数据存储到已经存在的变量中?
  • @IvánYoed,我还没有真正尝试过,但理论上它不应该工作,因为隔离不共享内存。不过,如果你能做到这一点,我想看看你的例子。
  • 我最近发布了一个关于此的问题并收到了一个很好的答案。也许你感兴趣stackoverflow.com/q/67181838/13766744
【解决方案3】:

我们可以用一句话说,

Isolates:Dart 是单线程的,但它能够使用 Isolates(许多进程)进行多线程处理。

Future:Future 是 dart 完成异步工作时返回的结果。这项工作通常在那个单线程中完成。

【讨论】:

    【解决方案4】:

    即使 dart 不是多线程的,也可以将 Isolate 与 Thread 进行比较。当 Futures 共享相同的内存时,它确实有自己的内存和事件循环

    Dart 能够生成独立进程,称为 Isolates(dart2js 中的网络工作者),当主程序不共享内存时,它们能够异步地在另一个进程(实际上是一个线程)能够做在不阻塞主线程的情况下进行计算。

    Future 在调用它的 Isolate 中运行,不一定是主隔离。

    我推荐这个article,它的解释比我好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-18
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      • 2018-11-12
      • 2015-08-02
      • 1970-01-01
      相关资源
      最近更新 更多