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

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

3天内不再提示

单线程也能开发异步任务?ACE JS框架到底是如何做到的

话说科技 2021-08-13 17:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

HarmonyOS 2提供了两种应用开发语言:Java和JS。Java线程特性能够让多任务并行,充分利用硬件资源开发出高性能的应用。而JS却是一个单线程语言,无法像Java一样创建新的Thread,用JS语言开发是否会导致硬件资源无法充分利用的情况呢?

本文给大家介绍“ACE JS的单线程异步机制”就是解决这个问题的。然而,说到 “单线程”与“异步”,大家可能会比较疑惑,因为单线程和异步在概念上是冲突的,单线程无法做到多任务并发,也就不会存在异步这种通信机制。

确实,JS语言本身是无法实现异步的,但是ACE JS框架却提供了多线程的宿主环境,通过消息通信机制让JS语言有了异步的属性,下面我们来详细描述其原理。

ACE开发框架

使用JS开发HarmonyOS应用,使用的开发框架名为ACE(Ability Cross-Platform Environment),该框架适用于手机、平板、智慧屏、智慧表、车机等设备,具备“一次开发,多端部署”的能力。

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

pYYBAGEWOIyATdaWAADtwa2aYQQ444.png

●Application

应用层表示开发者使用JS UI框架开发的FA应用,这里的FA应用特指JS FA应用。

●Framework

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

●Engine

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

●Porting Layer

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

ACE开发框架的线程模型

poYBAGEWOI2Ae7o0AAD6WYLdZrY885.png

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

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

●UI线程:负责应用界面的绘制刷新,与应用的进程号相同,又叫主线程。如果开发JS+JAVA的混合编程,JAVA PA(Particle Ability)的onStart/onConnect等Ability生命周期回调便是运行在主线程,若在这些生命周期回调上执行耗时操作则会导致JS UI的绘制刷新卡住。

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

●后台任务线程:这里是对ACE框架外部的后台线程的一个统称,并不单指一个线程,也并不唯一。后台任务线程包含了Java PA线程、文件操作API、网络访问API内部实现等相关线程。

下面我们结合测试代码来看一下这3个线程之间的关系。

JS线程与UI线程的关系

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

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

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

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');

}

将应用运行起来,点击两次按钮,得到如下Log:

poYBAGEWOI2AHLLyAAC_IDf7wvk861.png

从输出的Log中,我们可以看到这个JS FA进程号为22592,也就是说UI线程是22592;生命周期回调以及按钮响应均在24077线程,这个就是JS线程,所以JS线程与UI线程不是同一个线程。

并且我们尝试通过sleep方法阻塞JS线程,想观察JS线程阻塞是否会影响到UI线程的刷新。最终得出的结论是无论JS线程sleep多长时间,UI界面上的progress组件动画一直会不断刷新,按钮也会有按压效果变化,所以我们可以推测JS线程与UI线程的相互调用应该是通过某种消息机制完成的,而不是阻塞式的调用。

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

ACE JS框架提供了JS FA(Feature Ability)调用Java PA(Particle Ability)的机制,该机制提供了一种通道来传递方法调用、处理数据返回以及订阅事件上报。我们同样制作一个Demo来验证JS线程与Java PA线程的关系:

在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.callAbilityend'+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);

}

以上代码完成后,我们进行执行,得到的Log如下:

pYYBAGEWOI6AYZIJAAHEEAp7qeg938.png

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

JS线程的异步机制

上面从代码实验角度观察到了JS线程与其他线程的异步关系,那么JS线程是怎么处理来自其他多个线程的调用的呢?我们先来看一下传统的浏览器环境下的机制:

pYYBAGEWOJGAV9OgAAN5QOfulTo678.png

上图中,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 ACE开发框架同样遵循上述最基本的EventLoop调度机制,并且提供了更多的机制和API,让业务逻辑可以在外部线程执行,包含了上面提到的Java PA以及异步回调的系统能力API。其中,异步回调的系统能力API包含如文件系统操作和网络操作等,具体大家可以按照我们实验Demo的方法去尝试一下。

●参考

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

未来发展的展望

目前ACE JS应用内实现多线程的最佳方式是通过混合编程调用Java PA方式,但未来纯JS应用一定会越来越多,那么,只支持单线程的JS ACE框架的异步API能解决各种复杂场景的问题吗?

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

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

fqj

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

    关注

    30

    文章

    4941

    浏览量

    73136
  • 单线程
    +关注

    关注

    0

    文章

    18

    浏览量

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux多线程对比单线程的优势

    。「提高响应性」:线程可以使程序更加响应用户输入或其他事件,避免阻塞。线程相比单线程的优点:「并发性」:多线程可以同时执行多个任务,而
    发表于 12-01 06:11

    请问Keil中的map文件到底是什么意思?

    Keil中的map文件到底是什么意思?里面是如何进行相关执行操作的
    发表于 11-25 06:59

    一句话,多个命令同时执行,AI语音模组能多任务处理?

    、 Ai-WV02-32S   将语音识别、唤醒、语义理解等核心功能, 浓缩在一颗小小的模组中。 安信可AI语音模组支持 MCP 协议(Multi Command Processing,多命令并行处理) ,让语音交互从“单线程”进化为真正的“多任务协同”! 一句话唤醒“
    的头像 发表于 10-31 14:45 241次阅读
    一句话,多个命令同时执行,AI语音模组<b class='flag-5'>也</b>能多<b class='flag-5'>任务</b>处理?

    OPPO Pad 5搭载MediaTek天玑9400+芯片

    OPPO Pad 5 搭载 3nm 先进制程的天玑 9400+ 旗舰芯,全大核架构设计,内建大容量高速缓存,以更高的单线程和多线程任务处理性能,带来令人惊叹的日常应用、游戏等全场景应用体验,内置
    的头像 发表于 10-30 15:44 452次阅读

    IEC 到底是什么?为什么它能影响全球?

    IEC 到底是什么?为什么它能影响全球?
    的头像 发表于 09-04 17:07 2442次阅读

    【HZ-T536开发板免费体验】—— linux创建线程

    的执行任务成为单线程。多线程是程序中包含多个执行流,在一个程序中可以同时运行多个不同的线程来执行不同的任务。 多
    发表于 09-01 21:31

    Task任务:LuatOS实现“任务级并发”的核心引擎

    Task任务通过其强大的并发处理能力,使LuatOS能够在单线程环境中模拟多线程执行,通过协程的挂起与恢复机制,实现任务级的并行操作,显著提升系统效能。 sys核心库是LuatOS运行
    的头像 发表于 08-28 13:49 335次阅读
    Task<b class='flag-5'>任务</b>:LuatOS实现“<b class='flag-5'>任务</b>级并发”的核心引擎

    同步任务开发指导

    同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。 同步任务的实现需要考虑多
    发表于 06-19 07:57

    I/O密集型任务开发指导

    使用异步并发可以解决单次I/O任务阻塞的问题,但是如果遇到I/O密集型任务,同样会阻塞线程中其它任务的执行,这时需要使用多
    发表于 06-19 07:19

    RK3588核心板在边缘AI计算中的颠覆性优势与场景落地

    与低功耗。相比传统四核A72方案(如RK3399),单线程性能提升80%,多线程任务处理能力翻倍。 6TOPS独立NPU: 支持INT8/INT16混合精度计算,可直接部署YOLOv5
    发表于 04-15 10:48

    LuatOS协程深度解析:小白能10分钟学会,代码效率直接起飞!

    嵌入式开发如何兼顾效率与简洁?LuatOS协程给出完美答案!它用类线程的语法封装异步逻辑,让多任务开发
    的头像 发表于 04-10 15:23 450次阅读
    LuatOS协程深度解析:小白<b class='flag-5'>也</b>能10分钟学会,代码效率直接起飞!

    进程、线程、协程傻傻分不清?一文带你彻底扒光它们的\"底裤\"!

    权(yield)实现协作,单线程内玩出多任务的感觉。 技术细节: 协程切换成本≈打哈欠(0.1μs~1μs) 阻塞操作会直接让出CPU(比如等待网络请求时,自动切换到其他协程) 必须依附于线程(就像
    发表于 03-26 09:27

    摩尔线程图形显卡MTT S80实现DeepSeek模型部署

    摩尔线程“全功能”图形显卡MTT S80,不仅游戏渲染性能强大,能玩《黑神话:悟空》,现在还能本地部署DeepSeek R1蒸馏模型。搭配最新发布的MUSA SDK RC3.1.1版本,开发者直接用开源框架Ollama就
    的头像 发表于 02-21 15:46 4031次阅读
    摩尔<b class='flag-5'>线程</b>图形显卡MTT S80实现DeepSeek模型部署

    ADS1298的操作温度范围到底是多少?

    ADS1298是 0°Cto +70°C;工业级ADS1298I 是 –40°Cto +85°C。 现在不知道ADS1298的操作温度范围到底是多少?
    发表于 02-10 07:19

    蓝牙AOA定位系统如何做到高精准度?

    蓝牙AOA定位系统是一种高精度的室内定位技术,其高精准度是通过一系列高科技的技术和方法实现的。以下是给大家分析的几点关于如何做到高精准度的几个关键点:
    的头像 发表于 12-13 11:42 936次阅读