为什么 Dart 是单线程的语言却能支持异步?

在开始弄懂问题之前我们先来了解下两个非常重要的东西:

isolateevent loop

Isolate

如果你已经看过官方文档,相信已经对 isolate 有了一定的了解,这里,我想再重新讲一下。

ioslate 被翻译成中文是 隔离器 的意思,下文会统称为 隔离器

隔离器我们从字面上可以隐约感知到,它是一个单独的被隔离的器皿。是的,在Dart中,它就是这么一个被隔离的东西。

那么隔离的东西里面有什么呢?

它有一块自己的内存(Memory)以及一个单独的线程(Thread)。

那这个线程是干嘛的呢?

答案: 它 一直在运行事件循环(Event Loop)

如下图所示:

隔离器是不是唯一的?

在 Dart app 中 隔离器不是唯一的 ,可以手动创建多个隔离器。

利用 Isolate.spawn() 或者 Flutter 中的 compute() 来创建多个隔离器。

为什么要创建多个隔离器?

试想一下, 如果只有一个隔离器,那么做庞大计算时是不是很容易造成掉帧(计算密集型操作会让 App 卡顿)

当然也可以从上面两个创建隔离器的函数名中看出端倪。

创建出的隔离器与原先的 隔离器相互之间不能访问各自的内存及线程,它们只有一种交互模式

通过互相传递消息,A 隔离器发送一条消息给 B 隔离器,B 隔离器接收到消息后利用自己的事件循环来处理消息。

这样的好处是, 能够不用锁定隔离器中的内存分配及垃圾回收,因为只有一个线程,所以很容易就能知道内存有没有被修改(因为没有别的线程能访问这块内存空间) ,在 Flutter 中,对快速构建或拆除一个界面中的部分组件特别有效。

Event loop

上文中已经有提到事件循环,相信你已经对它有点印象了,它会负责处理收到的消息事件,当然它也是让 Dart 能够真正拥有异步能力的核心。

1. 事件循环是干嘛用的?

在一个 app 中,启动,退出,用户会点击,滑动,程序访问硬盘等等,这一系列的操作我们统称为事件,因为你不知道事件何时会发送过来,所以得有一个永不停歇不能阻塞的循环来等待处理事件。

2. 事件循环的运行机制

事件被被扔到一个事件队列中,而事件循环会从事件队列中取出最旧的事件处理,再返回下一个事件处理,以此类推直到事件队列中再也没有事件了。

当处理事件操作中存在一个中断(break),线程会先挂出,等待下一个事件。

3. 到底怎么异步啊?

相信绝大多数人看到这里还是没有想通为什么,综上,我就来讲解一下。

首先 一个App从启动到关闭,绝大部分的时间都在等待中 。 例如:等待用户操作,网络请求等等。

那么这种等待是不是阻塞的呢?肯定不是咯,否则还怎么玩!

刚才说了事件循环是永不停歇的,A 事件处理完后悔处理 B 事件,B 事件处理完了要处理 C事件。

这里传递的事件都不能够是阻塞型的事件,否则会造成 ANR,耗时操作记得使用异步对象。

Dart 中提供了一异步对象例如: FutureStream 他们都是非阻塞的。

这些异步对象都会告诉事件循环说: 待会来执行代码,你先忙你的。

这样子就形成了一个异步的机制。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章