0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HarmonyOS JS应用开发需要关注哪些线程?官方解析来啦~

话说科技 来源:话说科技 作者:话说科技 2021-09-06 15:25 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

作者:wuyawei,华为软件开发工程师

HarmonyOS 2提供了对两种开发语言的支持:Java和JavaScript(下文简称JS)。从事过Android开发的同学对Java都很熟悉了,其多线程特性能够让多任务并行执行,充分利用硬件资源开发出高性能的应用。在HarmonyOS 2上,JS目前无法像Java一样直接创建新的Thread,那么使用JS语言开发HarmonyOS应用是否会遇到硬件资源无法充分利用的情况呢?

虽然使用JS语言目前无法直接创建新的Thread,但是HarmonyOS的JS UI框架提供了多线程的宿主环境,可以帮助应用开发丰富的业务逻辑。在开发HarmonyOS 2应用时,开发者除了需要了解JS线程外,还需要关注哪些线程?这些线程之间的关系又是什么样的?下面让我们一起来研究一下。

一、HarmonyOS的JS UI框架

HarmonyOS的JS UI框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(Porting Layer),如下图所示:

HarmonyOS JS应用开发需要关注哪些线程?官方解析来啦

  • Application

应用层表示开发者使用JS UI框架开发的FA应用,这里的FA应用特指JS FA应用。https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-js-fa-developing-0000001063300612

  • Framework

前端框架层主要完成前端页面解析,以及提供MVVM(Model-View-ViewModel)开发模式、页面路由机制和自定义组件等能力。

  • Engine

引擎层主要提供动画解析、DOM(Document Object Model)树构建、布局计算、渲染命令构建与绘制、事件管理等能力。

  • Porting Layer

适配层主要完成对平台层进行抽象,提供抽象接口,可以对接到系统平台。比如:事件对接、渲染管线对接和系统生命周期对接等。

二、JS UI框架的线程模型

每个HarmonyOS JS应用,都是通过JS UI框架进行加载渲染的。HarmonyOS的JS UI框架包含了JS线程、UI线程、GPU线程、IO线程这4个线程,并且在JS UI框架外还会存在一类后台任务线程。

其中GPU线程与IO线程主要是JS UI框架初始化与页面加载渲染的过程需要的,为JS UI框架内部的专有线程,不会被应用直接操作到,应用不需要特别关注;UI线程、JS线程和后台任务线程会与应用开发代码相关,后面着重分析这三个线程的作用和关系。

  • UI线程:负责应用界面的绘制刷新,与应用的进程号相同,又叫主线程。如果开发JS+JAVA的混合编程(https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-fa-calls-pa-mechanism-0000001050022401),需要特别注意的是JAVA PA(Particle Ability)的onStart/onConnect等Ability生命周期回调便是运行在主线程,若在这些声明周期回调上执行耗时操作则会导致JS UI的绘制刷新卡住。

  • JS线程:应用的JS代码会被JS引擎解析执行,并运行在JS线程上,目前我们工程中看到的所有的JS代码都会执行在这个进程下唯一的JS线程上。

  • 后台任务线程:这是对JS UI框架外部的后台线程的一个统称,并不单指一个线程,也并不唯一。它包含了Java PA中onRemoteRequest()业务逻辑的执行线程、文件操作API、网络访问API内部实现等相关线程。

下面我们结合测试代码的来看一下这3个应用开发需要关注的线程之间的关系。

三、JS线程与UI线程的关系

为了验证JS线程与UI线程的关系,我们准备了一个实验性质的Demo,主要代码以及运行过程的Log如下:

首先我们在IDE建立一个Empty Ability(JS)模板的HelloWorld工程,在生命周期、按钮响应回调方法里增加Log以观察线程情况。刚创建的app.js中Application生命周期默认已经有Log,无需额外添加。

我们需要在自动创建的MainAbility.java中onStart/onTouchEvent回调函数增加HiLog打印:

HiLog.info(LABEL_LOG, "MainAbility::onStart");

HiLog.info(LABEL_LOG, "MainAbility::onTouchEvent");

我们只需要在主界面index.js文件中onInit增加日志:

CoffeeScript

console.info('page.default onInit');

然后在index.hml中增加一个button以及会一直进行动画的progress组件:

I'm a button

最后在index.js中增加按钮点击响应事件以及Log,并且尝试sleep阻塞js线程:

function sleep(delay) {

for (var t = Date.now(); Date.now() - t <= delay; );

}

onButtonClick() {

console.info('onButtonClick begin');

sleep(1000);

console.info('onButtonClick end');

}

我们将应用运行起来,点击一次按钮,会发现progress组件动画并不会因为onButtonClick阻塞了1秒钟而有任何暂停,我们一起来分析一下这个过程中的Log:

15:30:07.323 15870-15870/com.blancwu.test I 01100/MainAbility: MainAbility::onStart

15:30:07.342 15870-18938/com.blancwu.test I 03B00/JSApp: app Log: AceApplication onCreate

15:30:07.352 15870-18938/com.blancwu.test I 03B00/JSApp: app Log: page.default onInit

15:30:31.006 15870-15870/com.blancwu.test I 01100/MainAbility: MainAbility::onTouchEvent

15:30:31.041 15870-15870/com.blancwu.test I 01100/MainAbility: MainAbility::onTouchEvent

15:30:31.104 15870-15870/com.blancwu.test I 01100/MainAbility: MainAbility::onTouchEvent

15:30:31.106 15870-15870/com.blancwu.test I 01100/MainAbility: MainAbility::onTouchEvent

15:30:31.112 15870-18938/com.blancwu.test I 03B00/JSApp: app Log: onButtonClick begin

15:30:32.113 15870-18938/com.blancwu.test I 03B00/JSApp: app Log: onButtonClick end

从输出的Log中,时间点后面跟着的便是我们执行日志的代码行所在的进程号与线程号,刚才我们增加的日志均在15870这个进程下,这个进程下又存在15870线程以及18938线程。其中15870与进程号相同,这便是我们说的UI线程;我们在.js文件中增加的日志全都会在18938线程上打印出来,这个便是JS线程。

HarmonyOS JS应用开发需要关注哪些线程?官方解析来啦

在应用初始化时,首先进入MainAbility.java的onStart生命周期回调,然后才进入AceApplication、Page等JS代码逻辑;应用初始化完毕后,UI线程上便会持续刷新progress组件的动画,当用户点击按钮触发onButtonClick阻塞1秒时,因为阻塞的仅仅是JS线程,所以UI线程上progress组件的动画刷新并不会有任何影响,还是在持续刷新。所以我们可以确定JS线程与UI线程的相互调用应该是通过某种消息机制完成的,而不是阻塞式的调用。

四、JS线程与后台任务线程的关系

JS UI框架提供了JS FA(Feature Ability)调用Java PA(Particle Ability)的机制,该机制提供了一种通道来传递方法调用、处理数据返回以及订阅事件上报的机制,Java PA运行在一个独立的后台任务线程,可以支撑应用开发多线程的业务逻辑。我们同样制作一个Demo来验证JS线程与Java PA线程的关系:

在上一个Demo基础上,我们修改onButtonClick的JS代码,通过FeatureAbility.callAbility拉起并调用了名为一个类名为ServiceAbility的Java PA,并拿到返回结果:

var action = {};

action.bundleName = 'com.blancwu.test';

action.abilityName = 'com.blancwu.test.ServiceAbility';

action.messageCode = 1001;

action.abilityType = 0;

action.syncOption = 0;

console.info('FeatureAbility.callAbility begin' + JSON.stringify(action));

FeatureAbility.callAbility(action).then(function (value) {

console.info('FeatureAbility.callAbility async result ' + JSON.stringify(value));

})

console.info('FeatureAbility.callAbility end' + JSON.stringify(action));

在ServiceAbility的onRemoteRequest中增加Log输出,并sleep 1秒种,以便观察线程情况与之间关系:

@Override

public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException {

HiLog.info(LABEL_LOG, "onRemoteRequest begin " + code);

if (code == 1001) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

Map result = new HashMap();,>,>

result.put("result", 1);

reply.writeString(ZSONObject.toZSONString(result));

}

HiLog.info(LABEL_LOG, "onRemoteRequest end " + code);

return super.onRemoteRequest(code, data, reply, option);

}

以上代码完成后,我们进行执行,progress组件的动画同样不会被打断,得到的Log如下:

06-25 13:31:48.090 4133-5887/com.blancwu.test I 03B00/JSApp: app Log: FeatureAbility.callAbility begin{"bundleName":"com.blancwu.test","abilityName":"com.blancwu.test.ServiceAbility","messageCode":1001,"abilityType":0,"syncOption":0}

06-25 13:31:48.094 4133-5887/com.blancwu.test I 03B00/JSApp: app Log: FeatureAbility.callAbility end{"bundleName":"com.blancwu.test","abilityName":"com.blancwu.test.ServiceAbility","messageCode":1001,"abilityType":0,"syncOption":0}

06-25 13:31:48.112 4133-4133/com.blancwu.test E 01100/ServiceAbility: [8187916a4418bed, 399b373, f521b3] ServiceAbility::onStart

06-25 13:31:48.126 4133-5837/com.blancwu.test I 01100/ServiceAbility: [8187916a4418bed, 171378f, 385abb1] onRemoteRequest begin 1079135572

06-25 13:31:48.126 4133-5837/com.blancwu.test I 01100/ServiceAbility: [8187916a4418bed, 171378f, 385abb1] onRemoteRequest end 1079135572

06-25 13:31:48.126 4133-5837/com.blancwu.test I 00000/RemoteObject: [8187916a4418bed, 171378f, 385abb1] Java onRemoteRequest called

06-25 13:31:48.143 4133-5837/com.blancwu.test I 01100/ServiceAbility: onRemoteRequest begin 1001

06-25 13:31:49.145 4133-5837/com.blancwu.test I 01100/ServiceAbility: onRemoteRequest end 1001

06-25 13:31:49.145 4133-5837/com.blancwu.test I 00000/RemoteObject: Java onRemoteRequest called

06-25 13:31:49.151 4133-5887/com.blancwu.test I 03B00/JSApp: app Log: FeatureAbility.callAbility async result "{"result":1}"

整个执行过程可以描述如下图:

HarmonyOS JS应用开发需要关注哪些线程?官方解析来啦

我们观察到本次运行主进程(UI线程)号为4133,JS代码执行在JS线程(5887),Java PA响应onRemoteRequest执行在另一个后台任务线程(5837)。通过Log我们看到onRemoteRequst即使阻塞了后台任务线程1s也不会影响JS线程的执行以及主线程(UI线程)上动画的刷新,做到了JS线程与后台任务线程上的任务并行处理。

五、JS的异步机制

上面从代码实验角度观察到了应用开发中JS线程与其他线程的关系,那么JS线程是怎么与其他线程进行异步通信的呢?我们先来看一下传统的浏览器环境下的机制:

HarmonyOS JS应用开发需要关注哪些线程?官方解析来啦

上图中,JS线程中的函数调用会存在于栈(stack)中,栈中的函数可以调用浏览器环境提供的WebAPIs,包含了DOM、ajax、timeout等API,这些API会在浏览器环境提供的另外一个外部线程执行,执行完成后会在任务队列(callback queue)中加入对应的回调事件(如onClick、onLoad、onDone)。当栈中的代码执行完毕,即栈清空后,JS线程又会通过event loop取出任务队列中的下一个任务进行执行,以此类推完成整个的程序执行。更具体的机制可以去看阮一峰老师介绍JS EventLoop的文章。

JS EventLoop的介绍

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

HarmonyOS的JS UI框架同样遵循上述最基本的EventLoop调度机制,并且提供了更多的机制和API,让业务逻辑可以在外部线程执行;包括上面提到的Java PA机制以及还未提及的支持异步回调的系统能力API。其中,支持异步回调的系统能力API包含文件系统操作和网络操作等,感兴趣的同学可以按照我们实验Demo类似的方法去尝试一下。

● 文件系统操作API参考

https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-file-storage-0000000000629445

六、未来展望

目前HarmonyOS的JS应用内实现多线程的最佳方式是通过混合编程调用Java PA方式,但无法支持纯JS应用开发多线程业务,纯JS应用目前仅可使用框架提供的异步API了,那么这些异步API能解决各种复杂场景的问题吗?

JS线程加上异步API能够很好解决单个I/O阻塞的问题,但是如果遇到大量的I/O事件,比如批删除大量文件,通过for循环发起了大量异步任务,也会降低执行效率,甚至阻塞其他异步任务的执行。并且如果要使用JS语言开发计算密集型的任务,也无法在唯一的JS线程上进行。

这时就需要一个真正的JS多线程处理机制了,虽然目前HarmonyOS 2还未支持,但未来HarmonyOS会考虑规划出与HTML5类似提供支持WebWorker机制,支持开发出多线程的JS代码,提供给应用开发者更多的发挥空间。

fqj

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 线程
    +关注

    关注

    0

    文章

    508

    浏览量

    20753
  • HarmonyOS
    +关注

    关注

    80

    文章

    2146

    浏览量

    35536
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    HarmonyOSAI编程智能问答

    线程? 指定上下文问答 在对话框中输入@符号,或点击上方@Add Context按钮,可指定对单个或多个代码文件进行分析。点击图标开启光标上下文功能,该功能可识别光标位置和选中的代码片段,让CodeGenie分析指定文件和选中的代码片段。 本文主要从参考引用自Harmony
    发表于 09-03 16:17

    HarmonyOS 5】金融应用开发鸿蒙组件实践

    HarmonyOS 5】金融应用开发鸿蒙组件实践 ##鸿蒙开发能力 ##HarmonyOS SDK应用服务##鸿蒙金融类应用 (金融理财# 一、鸿蒙生态观察 2024 年 1 月 1
    的头像 发表于 07-11 18:20 743次阅读
    【<b class='flag-5'>HarmonyOS</b> 5】金融应用<b class='flag-5'>开发</b>鸿蒙组件实践

    ArkUI-X案例解析

    tab页,其中 tabs“溪村挑战赛” 使用了harmonyos的独有能力进行UI设计。由于无法通过Bridge实现跨平台改造,因此需要在Android/iOS平台部署时删除该tab页相关元素,同时相关
    发表于 06-23 22:40

    HarmonyOS 5】桌面快捷方式功能实现详解

    功能,是目前很常见的功能之一。 鸿蒙系统提供的**桌面快捷方式(Shortcuts)**功能,允许开发者为应用内常用功能创建直达入口,用户通过长按应用图标即可快速启动特定功能,大幅减少操作层级。 本文将结合地图导航场景,详细解析鸿蒙快捷方式的实现原理与
    的头像 发表于 06-21 16:42 1775次阅读
    【<b class='flag-5'>HarmonyOS</b> 5】桌面快捷方式功能实现详解

    鸿蒙5开发宝藏案例分享---Web开发优化案例分享

    开发者需关注API更新或在设计预加载策略时利用此特性。 预下载 (Pre-Fetch/DownLoad) 痛点: 页面里的图片、CSS、JS等资源,边下载边解析渲染,遇到大文件或慢
    发表于 06-12 17:20

    鸿蒙5开发宝藏案例分享---Web加载时延优化解析

    鸿蒙开发宝藏:Web加载完成时延优化实战 大家好呀!今天在翻鸿蒙开发者文档时,发现了一个隐藏的 性能优化宝藏区 ——官方竟然悄悄提供了超多实战案例!尤其是****Web加载完成时延分析这块,简直是
    发表于 06-12 17:11

    鸿蒙5开发宝藏案例分享---应用并发设计

    ?** 鸿蒙并发编程实战指南:解锁ArkTS多线程黑科技** 嘿,开发者朋友们! 今天给大家扒一扒鸿蒙官方文档里藏着的并发编程宝藏—— 100+实战场景解决方案 !从金融理财到游戏开发
    发表于 06-12 16:19

    HarmonyOS5云服务技术分享--ArkTS开发函数

    ) 最后说句掏心窝的话:本地调试真的能省下80%的打包等待时间,早用早轻松!开发过程中遇到任何问题,欢迎在评论区拍砖交流~ ? 祝各位开发者调试顺利,BUG退散!下次咱们再聊聊云函数的高阶玩法,记得关注哦~ ? (本文档基于
    发表于 05-22 17:29

    HarmonyOS5云服务技术分享--ArkTS开发Node环境

    ✨ 你好呀,开发者小伙伴们!今天我们来聊聊如何在HarmonyOS(ArkTS API 9及以上)中玩转云函数,特别是结合Node.js和HTTP触发器的开发技巧。文章会手把手带你从零
    发表于 05-22 17:21

    OpenHarmony应用开发精品课程第七期来啦

    OpenHarmony应用开发精品课程第七期来啦
    的头像 发表于 04-15 14:15 499次阅读
    OpenHarmony应用<b class='flag-5'>开发</b>精品课程第七期<b class='flag-5'>来啦</b>

    HarmonyOS NEXT 原生应用/元服务-ArkTS代码调试worker/taskpool调试

    代码中设置断点。 启动调试,当代码中断点命中时,调试窗口会新启动一个调试会话,显示 taskpool 线程的堆栈信息。 本文主要参考与引用自HarmonyOS官方文档。
    发表于 03-13 17:46

    HarmonyOS NEXT 原生应用/元服务调试概述

    一、概述 DevEco Studio提供了丰富的HarmonyOS应用/元服务调试能力,支持JS、ArkTS、C/C单语言调试和ArkTS/JS+C/C跨语言调试能力,并且支持三方库源码调试,帮助
    发表于 02-26 11:03

    HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发

    注重理论与实践的结合,提供让开发者快速上手的codelab编程练习,开发者能在实战中巩固所学,系统掌握核心开发技能。完成课程后,开发者可参加官方
    发表于 01-02 14:24

    HarmonyOS开发指导类文档更新速递(下)

    伴随着HarmonyOS 5.0.0 Release、HarmonyOS 5.0.1 Release版本的发布,HarmonyOS官网文档也带来了不少上新内容。本期HarmonyOS
    的头像 发表于 12-30 09:54 2116次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发</b>指导类文档更新速递(下)

    HarmonyOS Web开发性能优化指导

    体验。 预渲染:预渲染指在后台对需要加载的页面进行预先渲染,提前完成整个页面加载的流程。当用户需要访问该页面时,可以直接切换至前台展示,实现页面“秒开”的效果。预渲染要求在进行DOM解析
    发表于 12-06 08:41