当前位置: 首页 > news >正文

鸿蒙NEXT Function Flow Runtime开发指南:掌握下一代并发编程

面对多核处理器并发编程的复杂性,鸿蒙NEXT的Function Flow Runtime为你提供了一种更简洁高效的解决方案。

在鸿蒙应用开发中,如何高效利用多核处理器、如何管理复杂的异步任务、如何避免线程滥用导致性能下降,一直是开发者面临的挑战。华为鸿蒙NEXT推出的Function Flow Runtime Kit(FFRT) 正是为了解决这些问题而生的并发编程框架。

什么是Function Flow Runtime?

FFRT(Function Flow Runtime)是一种并发编程框架,旨在简化并发编程和任务调度的复杂性。它采用基于任务的调度方式,开发者只需关注任务及其依赖关系,而无需处理底层的线程和计算资源。

FFRT的核心概念

在深入了解FFRT之前,让我们先掌握一些基本概念:

  • 任务(Task):一种面向开发者的编程线索和面向运行时的执行对象,包含一组指令序列及其操作的数据上下文环境。

  • 任务依赖(Task Dependency):任务之间的依赖关系,决定了某个任务是否需要等待其他任务完成才能开始执行。

  • QoS(Quality of Service):定义了任务的服务质量等级,用于指示任务的优先级和资源分配。

  • Worker:执行任务的工作线程。每个Worker可以执行多个任务,由调度器负责管理和分配。

  • 调度(Scheduling):决定任务何时以及由哪个Worker执行的过程。

为什么选择FFRT?两种编程模型对比

在传统的线程编程模型中,程序员需要手动创建线程、管理线程生命周期和处理线程同步,这不仅复杂容易出错,还可能导致系统中有大量线程,造成资源浪费。

相比之下,FFRT的任务编程模型具有明显优势:

对比维度线程编程模型FFRT任务编程模型
并行度挖掘方式程序员通过创建多线程并把任务分配到每个线程静态分解应用为任务及其依赖,运行时动态调度
线程创建责任程序员负责,可能导致线程滥用FFRT运行时负责工作线程池管理
负载均衡静态映射任务到线程,可能导致负载不均运行时根据线程状态动态调度,均衡负载
调度开销内核态调度,开销大用户态协程调度,开销小
依赖表达通过线程同步操作增加线程切换显式表达输入输出依赖,运行时管理

FFRT采用基于协程的任务执行方式,可以提高任务并行度、提升线程利用率并充分利用多核平台的计算资源,保证系统对所有资源的集约化管理。

FFRT的三大并发范式

在实际业务中,FFRT支持三种不同的并发范式,应对各种复杂场景。

1. 串行队列(Serial Queue)

串行队列确保任务按照提交的顺序依次执行,适用于需要保持特定执行顺序的任务流。

适用场景

  • 顺序执行任务,避免乱序导致的数据不一致

  • 保证数据安全,避免多线程竞争条件

  • 简化开发,无需手动管理锁和同步机制

2. 并发队列(Concurrent Queue)

并发队列允许多个任务同时执行,提高并发性能,适用于并行计算和高效利用多核处理器。

适用场景

  • 提高并发度,充分利用多核处理器

  • 资源高效利用,减少任务等待时间

  • 灵活任务调度,支持优先级和QoS

3. 图依赖并发(Task Graph)

图依赖并发范式通过有向图表示任务及其依赖关系,能够清晰地管理和调度复杂依赖关系的任务。

适用场景

  • 复杂任务依赖关系管理

  • 动态任务调度,根据运行时条件调整

  • 最大化并行执行,提高资源利用率

FFRT实战:构建任务依赖图

FFRT图依赖并发范式支持任务依赖数据依赖两种方式构建任务依赖图。

任务依赖示例:流媒体视频处理

假设我们有一个视频处理流程,包含以下步骤:视频解析、视频转码、视频缩略图生成、视频水印添加和视频发布。其中转码和缩略图生成可以并行执行。

c

#include <stdio.h>
#include "ffrt/ffrt.h"void func_TaskA(void* arg) {printf("视频解析\n");
}void func_TaskB(void* arg) {printf("视频转码\n");
}void func_TaskC(void* arg) {printf("视频生成缩略图\n");
}void func_TaskD(void* arg) {printf("视频添加水印\n");
}void func_TaskE(void* arg) {printf("视频发布\n");
}int main() {// 提交任务Affrt_task_handle_t hTaskA = ffrt_submit_h_f(func_TaskA, NULL, NULL, NULL, NULL);// 提交任务B和C,它们都依赖于任务Affrt_dependence_t taskA_deps[] = {{ffrt_dependence_task, hTaskA}};ffrt_deps_t dTaskA = {1, taskA_deps};ffrt_task_handle_t hTaskB = ffrt_submit_h_f(func_TaskB, NULL, &dTaskA, NULL, NULL);ffrt_task_handle_t hTaskC = ffrt_submit_h_f(func_TaskC, NULL, &dTaskA, NULL, NULL);// 提交任务D,它依赖于任务B和Cffrt_dependence_t taskBC_deps[] = {{ffrt_dependence_task, hTaskB}, {ffrt_dependence_task, hTaskC}};ffrt_deps_t dTaskBC = {2, taskBC_deps};ffrt_task_handle_t hTaskD = ffrt_submit_h_f(func_TaskD, NULL, &dTaskBC, NULL, NULL);// 提交任务E,它依赖于任务Dffrt_dependence_t taskD_deps[] = {{ffrt_dependence_task, hTaskD}};ffrt_deps_t dTaskD = {1, taskD_deps};ffrt_submit_f(func_TaskE, NULL, &dTaskD, NULL, NULL);// 等待所有任务完成ffrt_wait();// 销毁任务句柄ffrt_task_handle_destroy(hTaskA);ffrt_task_handle_destroy(hTaskB);ffrt_task_handle_destroy(hTaskC);ffrt_task_handle_destroy(hTaskD);return 0;
}

数据依赖示例:斐波那契数列

数据依赖通过数据的生产者和消费者关系来表达任务依赖。当一个数据对象的签名出现在任务的in_deps中时,该任务是消费者任务;当出现在out_deps中时,该任务是生产者任务。

FFRT支持三种数据依赖关系:

  • Producer-Consumer依赖:生产者任务和消费者任务之间的依赖(Read-after-Write)

  • Consumer-Producer依赖:消费者任务和下一个版本生产者任务之间的依赖(Write-after-Read)

  • Producer-Producer依赖:一个版本生产者任务和下一个版本生产者任务之间的依赖(Write-after-Write)

FFRT高级特性

任务伙伴(Job Partner)

从API version 20开始,FFRT支持Job_Partner(任务伙伴)功能,解决多线程协作和动态并发调度问题。

适用场景

  • 多线程协作:部分功能需要在特定环境运行,其他功能可以在任何环境运行

  • 动态并发调度:根据任务数量动态调整worker数量,提升性能并降低调度开销

任务粒度优化建议

FFRT编程模型中任务的目标颗粒度最小为100us量级。开发者应注意合理控制任务颗粒度:颗粒度过小会增加调度开销,颗粒度过大会降低并行度。

FFRT与云函数集成

鸿蒙NEXT支持端云一体化开发,可以将FFRT与云函数相结合,构建更强大的应用。

创建云函数

在鸿蒙NEXT中创建云函数的步骤:

  1. 登录AppGallery Connect,进入云函数主界面

  2. 选择"函数"页签,点击"创建函数"

  3. 按照"函数配置 → 触发器 → 函数代码 → 层配置"引导顺序配置函数

端侧调用云函数

在端侧代码中调用云函数的示例:

typescript

import cloud from '@hw-agconnect/cloud'@Entry
@Component
struct MyIndex {@State message:string = ""build() {Column(){Button("调用hello云函数").onClick( async()=>{console.log("s")const result = await cloud.callFunction({name: 'hello', // 云函数名称version: "$latest", // 云函数版本params: {} // 传递参数})this.message = result.getValue().message})Text(this.message)}.width("100%").height("100%")}
}

最佳实践与性能优化

1. 合理选择并发范式

根据具体场景选择合适的并发范式:

  • 需要严格顺序执行 → 串行队列

  • 大量独立任务 → 并发队列

  • 复杂依赖关系 → 图依赖并发

2. 避免过度嵌套

虽然FFRT支持复杂的任务依赖关系,但过度嵌套可能导致代码难以维护。建议将复杂逻辑拆分为具名函数或中间变量。

3. 注意任务粒度

任务粒度影响应用执行性能。FFRT任务的目标颗粒度最小为100us量级,合理控制任务粒度可以平衡调度开销和并行度。

4. 利用语法糖提升代码可读性

鸿蒙NEXT的仓颉语言支持尾随Lambda、流操作符等语法糖,可以显著提升FFRT代码的可读性。

尾随Lambda示例

typescript

// 传统方式
process(function() {println("Hello, HarmonyOS!")
})// 尾随Lambda方式
process {println("Hello, HarmonyOS!")
}

流操作符示例

typescript

let numbers = [1, 2, 3, 4]
let sum = numbers|> map { it + 1 } // 映射:[2, 3, 4, 5]|> reduce(0) { acc, item => acc + item } // 归约:2+3+4+5=14
println(sum) // 输出:14

总结

Function Flow Runtime Kit是鸿蒙NEXT中强大的并发编程框架,它通过基于任务的编程模型,让开发者能从复杂的线程管理中解脱出来,专注于任务逻辑和依赖关系。无论是简单的顺序任务还是复杂的图依赖任务,FFRT都能提供高效、简洁的解决方案。

通过合理运用FFRT的三种并发范式——串行队列、并发队列和图依赖并发,结合云函数和现代语法特性,开发者可以构建出高性能、高可维护的鸿蒙应用,充分发挥多核处理器的计算能力,为用户提供更流畅的体验。

http://www.dtcms.com/a/486864.html

相关文章:

  • 遥控器外壳设计网站推荐哈尔滨建设信息网官网
  • 哈夫曼树 红黑树 B树 B+树 WTF!M3?(树形查找)
  • 【Linux内核】DMABUF 与文件描述符(fd)的绑定过程
  • AngularJS 模型
  • 网页设计与网站建设毕业设计成全看免费观看
  • MySQL数据库操作全指南(一)
  • 【项目】年会抽奖系统
  • 烟台建站程序如何用电脑主机做网站
  • Spring Boot 统一异常处理机制:设计原理与最佳实践
  • 【jenkins】构建安卓
  • Spring Boot 集成 SpringDoc OpenAPI(Swagger)实战:从配置到接口文档落地
  • 基于目标信息最大化的高分辨率雷达波形设计——论文阅读
  • 网站建设毕业答辩ppt模板顶尖网站建设
  • MCP传输模式选择指南:Stdio与HTTP的终极对比
  • 网站建设实习招聘wordpress 问卷调查
  • 效果图制作网站有哪些医院网站制作公司
  • MySQL 连接类型介绍
  • 网站开发编程入门学习网站设计要考虑的因素
  • sk09.【scikit-learn基础】--『无监督学习』之K均值聚类
  • 网站建设对于企业的意义wordpress上传网页
  • OFD转PDF技术方案:快速实现一键批量转换
  • 网站页面布局模板电商网站系统建设考试
  • 【完整源码+数据集+部署教程】 【运动的&足球】足球场景目标检测系统源码&数据集全套:改进yolo11-ASF-P2
  • 免费发布信息网站网址大全网站做cnzz流量统计
  • 手机群控软件实现多设备监控与测试的技术解析
  • 自定义Spring Boot Starter项目并且在其他项目中通过pom引入使用
  • 做网站后台系统的规范为什么会显示危险网站
  • [tile-lang] docs | 基准测试 | GEMM示例
  • 网站开发培训收费邯郸外贸网站建设
  • commons-imaging(图像处理库)