首页 > 其他分享 >谈谈flutter的线程

谈谈flutter的线程

时间:2024-09-13 19:46:10浏览次数:9  
标签:异步 Task Runner Isolate Flutter 谈谈 线程 flutter

本文同步发布于公众号:移动开发那些事谈谈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参考

公众号

标签:异步,Task,Runner,Isolate,Flutter,谈谈,线程,flutter
From: https://www.cnblogs.com/WoodJim/p/18412775

相关文章

  • 深入理解Redis线程模型
    Reids6.0之前版本的线程模型在讨论最新版本的Redis的线程模型之前呢,我们先来聊聊原来的Redis的线程模型:有人说,在6.0之前呢,Redis是单线程的,这么说其实也不太准确,为什么呢?因为Redis在4.0之后,就引入了多线程,比如说除了处理用户命令的主线程之外,还会起异步的线程去做一些资源释......
  • 线程池的拒绝策略
    线程池的拒绝策略是在任务无法被接受执行时,线程池采取的一种处理方式。Java中的ThreadPoolExecutor提供了几种内置的拒绝策略,可以通过构造函数或setRejectedExecutionHandler方法进行设置。以下是常见的拒绝策略:AbortPolicy(默认策略):AbortPolicy是默认的拒绝策略,当任务无法被接受......
  • Java21的虚拟线程来了
    1、什么是平台线程?平台线程是作为操作系统(OS)线程的薄包装器实现的。平台线程在其底层OS线程上运行Java代码,并且平台线程在其整个生命周期内捕获其OS线程。因此,可用的平台线程数量受限于OS线程的数量。平台线程通常具有较大的线程堆栈和由操作系统维护的其他资源。它们......
  • 面试官:线程池遇到未处理的异常会崩溃吗?
    首先,这个问题考察的是你对线程池execute方法和submit方法的理解,在Java线程池的使用中,我们可以通过execute方法或submit方法给线程池添加任务,但如果线程池中的程序在执行时,遇到了未处理的异常会怎么呢?接下来我们一起来看。1.execute方法execute方法用于提交一个不需要......
  • 多线程篇(线程池 - 整体介绍)(持续更新迭代)
    目录一、线程池(并发编程的艺术)1.Java中的线程池1.1.线程池的实现原理1.2线程池的使用1.线程池的创建2.向线程池提交任务3.关闭线程池4.合理地配置线程池5.线程池的监控1.3本章小结2.Executor框架2.1Executor框架简介1.Executor框架的两级调度模型2.......
  • 一个Android App最少有几个线程?实现多线程的方式有哪些?
    本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点多线程编程是Android应用开发中非常重要的一个环节,可以有效地提升应用的性能和用户体验。下面是对Android中多线程相关内容的详细介绍,包括app最少有几个线程。1.基本概念主线......
  • Java线程状态及生命周期
    基础概念Java线程在运行生命周期中的指定时刻只可能处于这6种不同状态的其中一个状态,分别是:NEW:初始状态,这是线程被创建出来但没有被调用start()。RUNNABLE:运行状态,线程被调用了start()等待运行的状态。BLOCKED:阻塞状态,等待WAITING:等待状态,表示该线程需要等待其他线程做出......
  • 线程池的应用-->2
    1.自定义线程工程当需要自定义线程的名字,线程的优先级,精灵线程状态时,需要自定义线程工厂。如何自定义线程工厂自定义工厂类,实现ThreadFactory接口,重写方法newThread()在创建线程池对象时,传递上述线程工厂对象publicclassTest5{publicstaticvoidmain(Strin......
  • 线程池介绍、参数、执行过程
    线程池管理一系列线程的资源池,提供了一种限制和管理线程资源的方式线程池一般用于执行多个不相关联的耗时任务,没有多线程的情况下,任务顺序执行,使用了线程池的话可让多个不相关联的任务同时执行好处降低资源消耗:频繁的线程创建和销毁会消耗系统资源,线程池可以复用已经创建......
  • day11-多线程
    一、线程安全问题线程安全问题出现的原因?存在多个线程在同时执行同时访问一个共享资源存在修改该共享资源线程安全:多个线程同时修改同一个资源取钱案例小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元如果小明和小红同时来取钱,并且2人各自......