本文同步发布于公众号:移动开发那些事谈谈flutter的线程

刚接触flutter的同学肯定会对fluter所谓的单线程架构很蒙逼,因为这与我们学开发时,各种语言里的多线程的介绍有点出入,而且手机的CPU现在基本都是多核的,操作系统不可能同一时间只在处理一件事件的,

那么flutter究竟是怎样实现 其所谓的单线程架构的呢? 在深入了解flutter的线程架构前,我们先来看看flutter使用的Dart语言的线程模型Isolate

1 Isolate

IsolateDart中一种轻量级的执行单元,类似于其他语言的线程,但又比线程更轻量级。其在底层实际还是依赖于操作系统提供的OSThread,与普通的线程的区别在于,Isolate拥有独立的内存,而普通的线程则需要与其他线程共享内存。因此每个Isolate相互独立,有自己单独内存空间(这个更接近于进程),不能在Isolate

之间共享内存。如果两个Isolate之间需要通信,可以通过端口port的方式进行数据的通信。

一个简单的Isolate之间通信的代码为:

   // 注册监听
var port = ReceivePort();
IsolateNameServer.registerPortWithName(
port.sendPort, "listen_name_demo");
port.listen((message) {
// 这里去处理接收到的信息
} // 发送消息
// 名字需要与前面注册的一样
final SendPort? sendPort =
IsolateNameServer.lookupPortByName("listen_name_demo");
if (sendPort != null) {
// 里面的消息的结构,与注册那边保持一致就可(可理解为约定的协议格式)
sendPort.send([id, status.value, progress]);
return;
}

Isolate 之间通过消息传递进行通信的,但 Isolate 内部是怎样对消息进行分发处理的呢?

1.1 内部消息处理

Isolate 内部是通过事件循环和消息队列来实现内部的消息的分发处理的,每个Isolate都会包含两个消息队列和一个事件循环

  • Microtask queue: 微任务事件队列,微事件队列的优先级比普通事件队列高
  • Event queue: 普通事件队列
  • Event Loop: 事件循环,不断在从队列中获取事件进行分发处理,类似于Android原生的Looper

1.2 异步处理

前面我们了解到Isolate是有消息队列的,但怎样给队列添加异步事件呢?答案是Future

一个简单的添加事件的代码为:

Future.delayed(const Duration(seconds: 3), () {
// 延迟3s后执行的异步操作
}); Future.microtask(() {
// 提交一个异步的微任务
});

而通过关键字Futureasyncawait的结合使用,我们可以把对应的方法变成一个异步的(也等于向普通事件队列里添加一个事件)

// async 说明这是一个异步的方法
Future<T> demoMethod() async {
// 具体的方法名
} // 在使用的地方可以使用await 等待这个异步方法执行完(不加await说明不用等这个异步方法执行完)
await demoMehtod();

2 线程模型

Flutter所谓的单线程架构是指如果我们不额外创建Isolate的话,它的逻辑都是跑在一个叫做RootIsolate上,那么这个Isolate是哪里创建呢?

答案就是Embedder(不知道Embedder的同学,可以网上找一张Flutter的架构图看看)。EmbedderFlutter的适配层,用于适配不同的操作系统,负责原生平台插件,

线程管理等功能。Embedder 提供了四个Task Runner

  • Platform Task Runner:与平台的主线程相对应,用于处理与平台的交互;
  • UI Task Runner:用于执行 Dart 代码,处理 UI 渲染和帧更新(Root Isolate就是运行在这里)。
  • GPU Task Runner:用于执行 GPU 绘制任务。
  • IO Task Runner:用于执行输入/输出任务,如文件读写、网络操作等;

2.1 Platform Task Runner

Runner运行所有在线程为原生的主线程(也就是我们经常说的UI线程),主要用于:

  • Flutter Engine层进行交互
  • 处理平台(Android,iOS,Web等)的消息

尽管是运行在原生的主线程,但在这个Runner里做耗时的操作并不会导致整个应用的卡顿,不过一般也不建议在这里做比较耗时的操作;

2.2 UI Task Runner

Runner运行所有在线程为原生的子线程,主要用于:

  • 执行Dart代码,也就是执行Root Isolate的逻辑
  • 执行渲染与处理Vsync信号,将Widget转换生成Layer Tree
  • 处理原生的Plugin消息
  • 定时器,microtasks任务;

2.3 GPU Task Runner

Runner运行所有在线程为原生的子线程,主要用于:

  • 执行GPU相关的指令;
  • UI Task生成的Layer Tree 转化为GPU可执行的指令;

同样的,虽然是运行在原生的子线程里,但阻塞该线程会引起应用的卡顿,

2.4 IO Task Runner

Runner运行所有在线程为原生的子线程,主要用于:资源文件相关的处理,如处理图片数据;

3 总结

综上所述,Flutter是通过以下几个部分来实现其线程的管理的:

  • Isolate及其事件循环和消息队列
  • 异步处理的语法糖,如async/awaitFuture/Stream
  • Embedder提供了四个Task Runner

4参考

公众号

谈谈flutter的线程的更多相关文章

  1. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  2. 谈谈Java的线程池设计

    在实际项目中,如果因为想异步执行暂时性的任务而不断创建线程是很浪费资源的事情(当一个任务执行完后,线程也没用了).这种情况下,最好是将任务提交给线程池执行. 所谓池,就是将管理某一种资源,对资源进行复 ...

  3. Flutter 多引擎支持 PlatformView 以及线程合并解决方案

    作者:字节移动技术-李皓骅 摘要 本文介绍了 Flutter 多引擎下,使用 PlatformView 场景时不能绕开的一个线程合并问题,以及它最终的解决方案.最终 Pull Request 已经 m ...

  4. Flutter异步与线程详解

    一:前言 - 关于多线程与异步 关于 Dart,我相信大家都知道Dart是一门单线程语言,这里说的单线程并不是说Dart没有或着不能使用多线程,而是Dart的所有API默认情况下都是单线程的.但大家也 ...

  5. java 线程的几种状态

    java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在正常 ...

  6. Java 线程的状态

    Java Thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在正常 ...

  7. .NET中 类型,对象,线程栈,托管堆在运行时的关系

    .NET中 类型,对象,线程栈,托管堆在运行时的关系 The Relationship at Run Time between Types,Objects,A Thread's Stack,and T ...

  8. [读书心得] .NET中 类型,对象,线程栈,托管堆在运行时的关系

    .NET中 类型,对象,线程栈,托管堆 在运行时的关系 The Relationship at Run Time between Types,Objects,A Thread's Stack,and ...

  9. JAVA中线程的状态

    java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW:至今尚未启动的线程的状态. RUNNABLE:可运行线程的线程状态. ...

  10. 【转】java 线程的几种状态

    java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在正常 ...

随机推荐

  1. DOS下的网络管理命令

    DOS下的网络管理命令 一. 实验目的 掌握DOS下的网络管理命令 二. 实验内容和要求 在DOS环境下用不同的网络管理命令,实现不同的网络管理功能 三. 实验方法.步骤及结果测试 1.  原理分析及 ...

  2. 3.1 Linux文件系统的层次结构

    通过学习<Linux一切皆文件>一节我们知道,平时打交道的都是文件,那么,应该如何找到它们呢?很简单,在 Linux 操作系统中,所有的文件和目录都被组织成以一个根节点"/&qu ...

  3. Rsync远程同步知识点总结

    Rsync: 简介:是一个开源的快速备份工具.可以在不同主机之间镜像同步整个目录,支持增量备份,保持链接(硬链接.软连接)和权限,且采用优化同步算法,传输前执行压缩(传输过程中效率加快了,但是会增加c ...

  4. PostgreSQL中将对象oid和对象名相互转换

    PostgreSQL中将对象oid转为对象名 使用pg的内部数据类型将对象oid转为对象名,可以简化一些系统视图的关联查询. 数据库类型转换对应类型的oid 可以用以下数据库类型转换对应类型的oid( ...

  5. 细说MySql索引原理

     MySQL索引   MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 可以类比字典,如果要查"mysql"这个单词,我们肯定需要定位 ...

  6. 低功耗4G模组Air780E快速入门:固件的远程升级

    ​ 今天我们学习Air780E快速入门之固件的远程升级,小伙伴们,学起来吧! 一.生成差分包 合宙的远程升级支持使用合宙云平台和自建服务器,此例程使用的是合宙云平台. 1.1 准备新旧版的core和脚 ...

  7. i-MES生产制造管理系统-可视化看板

    可视化看板最主要的目的是为了将生产状况透明化,让大家能够快速了解当前的生产状况以及进度,通过大数据汇总分析,为管理层做决策提供数据支撑,看板数据必须达到以下基本要求: 数据准确--真实反映生产情况 数 ...

  8. 鸿蒙开发Hvigor任务简介

    编译构建工具DevEco Hvigor(以下简称Hvigor)是一款基于TS实现的构建任务编排工具,主要提供任务管理机制,包括任务注册编排.工程模型管理.配置管理等关键能力,提供专用于构建和测试应用的 ...

  9. 使用wxpython开发跨平台桌面应用,设计系统的登录界面

    一般的系统登统界面,设计好看一些,系统会增色不少,而常规的桌面程序,包括Web上的很多界面,都借助于背景图片的效果来增色添彩,本篇随笔介绍基于WxPython来做一个登录界面效果,并对系统登录界面在不 ...

  10. nano编辑器保存退出

    nano的编辑器保存推出 使用 ctrl x 然后提示Y N 是否保存 写入,输入Y即可 然后再Enter 确认就可以了