在做应用开发的时候,开发语言的选择很重要。例如,Java语言的线程特性可以使多个任务并行进行,从而充分利用硬件资源开发高性能的应用程序。HarmonyOS2提供的应用开发语言不仅包括多线程的Java语言,还包括单线程的JS语言。那么JS语言是如何充分利用硬件资源开发高性能应用的呢?为此,鸿蒙OS提出了“ACEJS单线程异步机制”来解决这个问题。虽然JS语言本身不能实现异步功能,但是ACEJS框架提供了一个多线程的宿主环境。通过消息通信机制,JS语言具有异步的特性。接下来,我们来了解一下具体的实现原理。ACE开发框架使用JS开发HarmonyOS应用。使用的开发框架称为ACE(AbilityCross-PlatformEnvironment)。该框架适用于手机、平板、智慧屏、智能手表、车机等设备。能力。ACE框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(PortingLayer),如下图所示:应用:应用层代表开发者使用JSUI框架Application开发的FA,这里的FA应用特指JSFA应用;Framework:前端框架层主要完成前端页面解析,提供MVVM等能力(Model-View-ViewModel)开发模式、页面路由机制和自定义组件;Engine:引擎层??主要提供动画解析、DOM(DocumentObjectModel)树构建、布局计算、渲染命令构建与绘制、事件管理等能力;PortingLayer:适配层主要完成平台层的抽象,提供抽象接口,可以对接系统平台米。例如:事件对接、渲染管线对接、系统生命周期对接等ACE开发框架的线程模型每一个HarmonyOSJS应用都是通过上图所示的ACE开发框架来加载和渲染的。ACE开发框架包括JS线程、UI线程、GPU线程、IO线程,在ACE框架之外还会有一类后台任务线程。其中,GPU线程和IO线程是ACE框架内部的私有线程,主要用于ACE框架的初始化和页面加载渲染过程;UI线程、JS线程和后台任务线程与应用程序开发代码相关:UI线程:负责应用程序界面的绘制刷新,与应用程序的进程号相同,也称为主线程。如果开发JS+JAVA混合编程,JAVAPA(ParticleAbility)Ability生命周期回调如onStart/onConnect运行在主线程。如果对这些生命周期回调进行耗时操作,会导致JSUI的渲染卡死。JS线程:应用的JS代码会被JS引擎解析执行,运行在JS线程上,而JS是单线程语言,所以我们项目中看到的所有JS代码都会在这个进程中执行.唯一的JS线程。后台任务线程:这是ACE框架之外的后台线程的总称,不是一个线程,也不是唯一一个。后台任务线程包括JavaPA线程、文件操作API、网络访问API内部实现等相关线程。下面我们结合测试代码来分析一下这三个线程的作用和关系。JS线程和UI线程的关系为了验证JS线程和UI线程的关系,我们准备了一个实验Demo,主要代码和运行过程的日志如下:首先,我们创建一个EmptyAblity(JS)在IDE中模板HelloWorld项目,在生命周期和按钮响应回调方法中添加Log,观察线程情况。新建的app.js中的Applicationlifecycle默认已经有Log了,不用再添加。我们只需要在主界面index.js文件的onInit中添加一条log即可:console.info('page.defaultonInit');然后在index.hml中添加一个按钮和一个始终动画的进度组件:响应事件并登录index.js,尝试休眠阻塞js线程:functionsleep(delay){for(vart=Date.now();Date.now()-t<=delay;);}onButtonClick(){console.info('onButtonClickbegin');sleep(1000);console.info('onButtonClickend');}将运行应用程序,点击按钮两次,得到如下Log:从输出Log,我们可以看到JSFA进程号为22592,即UI线程为22592;生命周期回调和按钮响应都在24077线程,这里是JS线程,所以JS线程和UI线程不是同一个线程。而我们尝试通过sleep方法阻塞JS线程,想观察阻塞JS线程是否会影响UI线程的刷新。最终得出的结论是,无论JS线程休眠多长时间,UI界面上进度组件的动画都会一直刷新,按钮也会有按下效果的变化,所以我们可以推测两者之间的相互调用JS线程和UI线程应该是通过一些这种消息机制完成的,而不是阻塞调用。JS线程与后台任务线程的关系ACEJS框架提供了JSFA(FeatureAbility)调用JavaPA(ParticleAbility)的机制,提供了传递方法调用、处理数据返回、订阅事件上报的通道.JS线程和JavaPA线程的关系可以通过下面的Demo来验证:在JS中,我们通过FeatureAbility.callAbility拉起调用一个名为ServiceAbility的JavaPA,得到返回结果:varaction={};action.bundleName='com.blancwu.test';action.abilityName='com.blancwu.test.ServiceAbility';action.messageCode=1001;action.abilityType=0;action.syncOption=0;console.info('FeatureAbility.callAbilitybegin'+JSON.stringify(action));FeatureAbility.callAbility(action).then(function(value){console.info('FeatureAbility.callAbilityasyncresult'+JSON.stringify(value));})console.info('FeatureAbility.callAbilityend'+JSON.stringify(action));在ServiceAbility的onRemoteRequest中增加Log输出,休眠1秒观察线程情况与:@OverridepublicbooleanonRemoteRequest(intcode,MessageParceldata,MessageParcelreply,MessageOptionoption)throwsRemoteException{HiLog.info(LABEL_LOG,"onRemoteRequestbegin"+code);if(code==1001){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}Map
