当前位置: 首页 > 科技观察

单线程开发异步任务?ACEJS框架是如何实现的

时间:2023-03-14 16:25:02 科技观察

在做应用开发的时候,开发语言的选择很重要。例如,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();}Mapresult=newHashMap();result.put("result",1);reply.writeString(ZSONObject.toZSONString(result));}HiLog.info(LABEL_LOG,"onRemoteRequestend"+code);returnsuper.onRemoteRequest(code,data,reply,option);}完成以上代码并执行后,得到的Log如下:我们观察到本次运行的主进程(UI线程)数量为4133,JS代码在JS线程5887中执行,JavaPA响应onRemoteRequest,在另一个后台任务中执行通过线程5837的Log,我们可以看到,即使onRemoteRequst阻塞后台任务线程1s,也不会影响JS线程的并行执行和动画在线程上的刷新主线程(UI线程),让JS线程和后台任务线程异步执行事务。JS线程的异步机制从代码实验的角度观察了JS线程与其他线程的异步关系,那么JS线程如何处理来自其他多线程的调用呢?首先我们看一下传统浏览器环境下的运行机制:上图中,JS线程中的函数调用会存在栈(stack)中,栈中的函数可以调用浏览器提供的WebAPI环境,包括DOM、ajax、timeout等API,这些API会在浏览器环境提供的另一个外部线程中执行,相应的回调事件(如onClick、onLoad、onDone)会被添加到任务队列(callbackqueue)执行后。当栈中的代码执行完毕,也就是清空栈后,JS线程会通过事件循环取出任务队列中的下一个任务执行,以此类推完成整个程序的执行。HarmonyOSACE开发框架也沿用了上述最基本的EventLoop调度机制,并提供了更多的机制和API让业务逻辑在外线程执行,包括上述的JavaPA和异步回调系统能力API。其中,异步回调的系统能力API包括文件系统操作、网络操作等,具体可以按照我们实验demo的方法进行尝试。●未来发展前景请参考https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-file-storage-0000000000629445。目前ACEJS应用实现多线程最好的方式就是通过混合未来随着纯JS应用越来越多,仅支持单线程的JSACE框架的异步API无法解决各种复杂的场景问题。单线程JS加异步API可以很好的解决单次I/O阻塞的问题,但是如果遇到大量的I/O事件,比如批量删除大量文件,启动大量异步任务通过for循环,也会降低执行效率,甚至会阻塞其他异步任务的执行。而如果要用JS语言开发计算量大的任务,在唯一的JS线程上是做不到的。这时候就需要真正的JS多线程处理机制了。虽然HarmonyOS2还没有支持,但未来HarmonyOS会考虑规划类似HTML5的WebWorker机制,支持开发多线程的JS代码进行应用开发。更大的发展空间。