Dart 异步编程之 Isolate 和事件循环

简介: 这是我参与8月更文挑战的第 14天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战,尽管 Dart 是个单线程任务,但它提供 Future、Stream、后台任务以及其他特性用于编写现代异步程序以及响应式程序(Flutter)。本文讲的是 Dart 后台任务的基础:Isolate 和事件循环。

这是我参与8月更文挑战的第  14天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战

尽管 Dart 是个单线程任务,但它提供 Future、Stream、后台任务以及其他特性用于编写现代异步程序以及响应式程序(Flutter)。本文讲的是 Dart 后台任务的基础:Isolate 和事件循环。

我们先从 Isolate 开始。

Isolates


大多数应用程序中,线程的数量都不止一个。多个线程可以互不干扰地并发执行,并共享进程的全局变量和堆的数据。 线程的访问非常自由,它可以访问进程内存里的所有数据,甚至包括其他线程的堆栈 《程序员的自我修养》


所有的 Dart 代码都运行在 Isolate 中。Isolate 有自己私有的内存空间和一个基于事件循环的线程。

网络异常,图片无法展示
|

在其他很多语言中,比如 C++,多个线程可运行任何代码并共享内存。但 Dart 中每个线程在其自己的 Isolate 中,有自己的内存,线程只处理事件(后面很快会详细展开)。

大部分 Dart 应用在一个 Isolate 中运行全部代码,也可以根据需要创建更多 Isolate。如果某个操作计算量如此之大以至于它在主 Isolate 运行中会导致掉帧,可以使用 Isolate.spawn()Flutter’s compute() function 方法。这些方法都会创建独立的 Isolate 来做密集计算,让主 Isolate 专注重建和渲染 Widget 树。

网络异常,图片无法展示
|

新创建的 Isolate 有自己的事件循环和内存,原先的 Isolate (即创建新 Isolate 的那个 Isolate) 不能访问这些内存。这种机制正是 Isolate 名字的来源:内存块之间彼此隔离

事实上,Isolate 之间能协作的唯一方式是消息传递。一个 Isolate 可以向另一个 Isolate 发送消息,接收方在其事件循环处理收到的消息。

网络异常,图片无法展示
|

缺少共享内存听起来过于严格,尤其是你之前用过 Java 或 C++,但它给 Dart 开发者带来一些重要的好处。

比如,Isolate 中内存分配和垃圾回收不需要锁定。Isolate 中只有一个线程,如果它不是很忙的话,内存并不会快速变化,所以不必锁定。这非常适合 Flutter 应用,它时常要迅速地构建和销毁 Widget 树。

Event loops

现在你已经了解 Isolate 了,再来看看事件循环是如何让异步代码变成可能的吧。

想像一下应用沿着时间线的运行过程。应用启动,应用停止,之间发生一串串事件:磁盘 IO,用户手势以及类似一些事件。

应用无法预测事件何时发生、以何种顺序发生,它必须在单个线程中处理所有事件并且保证不阻塞。所以应用会运行一个事件循环。它从事件队列中取出最老的事件进行处理,然后再取下一个事件,依次进行,直到事件队列为空。

应用一直在运行:你点击屏幕、下载数据、触发定时器。事件循环一直在运行,每次处理一个事件。

网络异常,图片无法展示
|

事件循环空闲时,线程会暂停并循环下一个事件。这时可能触发垃圾回收器等等。Dart 为异步编程提供的所有高级 API 和语言特性,如 Future、Stream、async/await,都是基于和围绕这个基本的循环。

比如,某个按钮用于发起网络请求,就像这样:

RaisedButton(
  child: Text('Click me'),
  onPressed: () {
    final myFuture = http.get('https://example.com');
    myFuture.then((response) {
      if (response.statusCode == 200) {
        print('Success!');
      }
    });
  },
)
复制代码

你运行应用时,Flutter 构建按钮并显示到屏幕,之后应用开始等待。

应用的事件循环处于空闲,等待下一个事件。当按钮等待点击时,跟按钮不相关的事件可能发生并进入到事件队列被处理。当点击事件发生时,最终会进入队列。

点击事件被取到,等待处理。Flutter 看到这个事件,它的渲染系统说 “事件坐标跟 RaisedButton 匹配”,所以 Flutter 执行 onPressed 函数。这个函数会发起网络请求(返回一个 Future)并使用 then() 方法注册 completion handler。

整个过程就是这样的。事件循环处理完点击事件后将其抛弃。

onPressedRaisedButton 的一个属性,而网络事件为 Future 添加了一个回调,但两者都是在相同的基本操作。它们都是在告诉 Flutter,”你好,一会儿将发生某个事件,你记得执行该事件的代码。”

onPressed 在等待点击,而 Future 在等待网络数据,从 Dart 的视角,这些都是队列中的事件。

这也正是 Dart 中异步代码的工作方式。Future、Steam、以及 async/await,这些 API 都是你告诉 Dart 事件循环执行代码的一种方式。

如果再来回头看刚才的例子,你可以准确地看到它是如何为特定的事件被分解成一小块一小块的。

  1. 初始的 UI 构建事件
  2. 点击事件
  3. 网络响应事件
RaisedButton( // (1)
  child: Text('Click me'),
  onPressed: () { // (2)
    final myFuture = http.get('https://example.com');
    myFuture.then((response) { // (3)
      if (response.statusCode == 200) {
        print('Success!');
      }
    });
  },
)
复制代码

你习惯异步代码之后,到处都可以看到这些模式。理解事件循环对你跟高级 API 打交道时同样有帮助。

总结

我们简单地了解了 Dart 中的 Isolate、事件循环以及异步编程基础。



相关文章
|
2月前
|
存储 Linux 调度
协程(coroutine)的原理和使用
协程(coroutine)的原理和使用
|
14天前
|
机器学习/深度学习 开发框架 Dart
Flutter asynchronous 异步编程技巧
本文深入探讨了Flutter中的异步编程技巧,包括Future、Microtask及并发处理的最佳实践。文章详细讲解了Future.wait、FutureBuilder和Microtask的应用,帮助开发者提升应用性能。通过实例演示了如何利用Future.wait实现并发执行,FutureBuilder简化UI构建,以及Microtask的高优先级执行特性。适合希望优化Flutter应用异步性能的开发者阅读。
|
4月前
|
PHP 调度 容器
Swoole 源码分析之 Coroutine 协程模块
协程又称轻量级线程,但与线程不同的是;协程是用户级线程,不需要操作系统参与。由用户显式控制,可以在需要的时候挂起、或恢复执行。
75 1
Swoole 源码分析之 Coroutine 协程模块
|
3月前
|
存储 调度 Python
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。
|
5月前
|
程序员 Python
探索Python中的异步编程:从回调地狱到协程魔法
本文探讨了Python中的异步编程,从传统的回调地狱到现代的协程技术。通过对回调函数、多线程、多进程和协程的对比分析,展示了协程在提高代码性能和可维护性方面的优势,并介绍了如何使用asyncio库实现异步编程的实践方法。
|
5月前
|
编解码 Dart UED
Flutter单线程异步及Isolate使用过程遇到的问题
Flutter单线程异步及Isolate使用过程遇到的问题 在Flutter中,所有的代码都运行在单线程中。这意味着如果我们的代码执行时间过长,就会导致UI线程卡顿,影响用户体验。因此,Flutter提供了一些异步机制来解决这个问题。
142 0
|
10月前
|
Go 调度 C#
Unity——协程(Coroutine)
Unity——协程(Coroutine)
287 0
|
Dart 调度
Dart事件循环机制
Dart事件循环机制
94 0
|
网络协议 关系型数据库 MySQL
swoole协程框架?
Swoole是一个高性能的PHP扩展,可以用于构建异步、并发和高性能的网络应用。它提供了许多底层网络通信和多进程管理的功能,使得开发者可以更轻松地编写高性能的服务器程序。
93 0
|
Dart JavaScript 前端开发
《深入浅出Dart》事件循环和协程机制
事件循环和协程机制 Dart实现异步的方式同Javascript类似,如果你掌握Javascript的事件循环机制,那么学习Dart的异步机制就非常简单了 在 Dart 中,事件循环和协程是实现异步编程的核心机制。它们使得我们能够以非阻塞的方式处理异步操作,并允许在异步操作期间暂停和继续执行代码。本文将深入探讨 Dart 的事件循环和协程机制,并结合代码示例进行详细说明。
208 0