偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

單線程開(kāi)發(fā)異步任務(wù)?ACE JS框架是如何實(shí)現(xiàn)的

開(kāi)發(fā) 開(kāi)發(fā)工具
HarmonyOS ACE開(kāi)發(fā)框架遵循EventLoop調(diào)度機(jī)制,并且提供了更多的機(jī)制和API,讓業(yè)務(wù)邏輯可以在外部線程執(zhí)行,通過(guò)消息通信機(jī)制讓JS語(yǔ)言有了異步的屬性。

做應(yīng)用開(kāi)發(fā)時(shí),開(kāi)發(fā)語(yǔ)言的選擇至關(guān)重要。例如Java語(yǔ)言的線程特性能夠讓多任務(wù)并行,從而充分利用硬件資源開(kāi)發(fā)出高性能的應(yīng)用。而HarmonyOS 2提供的應(yīng)用開(kāi)發(fā)語(yǔ)言中,不僅有多線程的Java語(yǔ)言,還有單線程的JS語(yǔ)言。

那JS語(yǔ)言該如何充分利用硬件資源開(kāi)發(fā)出高性能的應(yīng)用呢?為此,HarmonyOS提出了“ACE JS的單線程異步機(jī)制”來(lái)解決這一問(wèn)題。

雖然,JS語(yǔ)言本身是無(wú)法實(shí)現(xiàn)異步功能,但是ACE JS框架提供了多線程的宿主環(huán)境,通過(guò)消息通信機(jī)制讓JS語(yǔ)言有了異步的屬性,接下來(lái)我們來(lái)了解下具體的實(shí)現(xiàn)原理。

ACE開(kāi)發(fā)框架

使用JS開(kāi)發(fā)HarmonyOS應(yīng)用,使用的開(kāi)發(fā)框架名為ACE(Ability Cross-Platform Environment),該框架適用于手機(jī)、平板、智慧屏、智慧表、車機(jī)等設(shè)備,具備“一次開(kāi)發(fā),多端部署”的能力。

ACE框架包括應(yīng)用層(Application)、前端框架層(Framework)、引擎層(Engine)和平臺(tái)適配層(Porting Layer),如下圖所示:

  • Application:應(yīng)用層表示開(kāi)發(fā)者使用JS UI框架開(kāi)發(fā)的FA應(yīng)用,這里的FA應(yīng)用特指JS FA應(yīng)用;
  • Framework:前端框架層主要完成前端頁(yè)面解析,以及提供MVVM(Model-View-ViewModel)開(kāi)發(fā)模式、頁(yè)面路由機(jī)制和自定義組件等能力;
  • Engine:引擎層主要提供動(dòng)畫解析、DOM(Document Object Model)樹(shù)構(gòu)建、布局計(jì)算、渲染命令構(gòu)建與繪制、事件管理等能力;
  • Porting Layer:適配層主要完成對(duì)平臺(tái)層進(jìn)行抽象,提供抽象接口,可以對(duì)接到系統(tǒng)平臺(tái)。比如:事件對(duì)接、渲染管線對(duì)接和系統(tǒng)生命周期對(duì)接等。

ACE開(kāi)發(fā)框架的線程模型

每個(gè)HarmonyOS JS應(yīng)用,都是通過(guò)上圖所示的ACE開(kāi)發(fā)框架進(jìn)行加載渲染的。ACE開(kāi)發(fā)框架包含了JS線程、UI線程、GPU線程、IO線程,并且在ACE框架外還會(huì)存在一類后臺(tái)任務(wù)線程。其中GPU線程與IO線程為ACE框架內(nèi)部的專有線程,主要作用于ACE框架初始化與頁(yè)面加載渲染的過(guò)程;UI線程、JS線程和后臺(tái)任務(wù)線程會(huì)與應(yīng)用開(kāi)發(fā)代碼相關(guān):

  • UI線程:負(fù)責(zé)應(yīng)用界面的繪制刷新,與應(yīng)用的進(jìn)程號(hào)相同,又叫主線程。如果開(kāi)發(fā)JS+JAVA的混合編程,JAVA PA(Particle Ability)的onStart/onConnect等Ability生命周期回調(diào)便是運(yùn)行在主線程,若在這些生命周期回調(diào)上執(zhí)行耗時(shí)操作則會(huì)導(dǎo)致JS UI的繪制刷新卡住。
  • JS線程:應(yīng)用的JS代碼會(huì)被JS引擎解析執(zhí)行,并運(yùn)行在JS線程上,而JS又是單線程語(yǔ)言,所以目前我們工程中看到的所有的JS代碼都會(huì)執(zhí)行在這個(gè)進(jìn)程下唯一的JS線程上。
  • 后臺(tái)任務(wù)線程:這里是對(duì)ACE框架外部的后臺(tái)線程的一個(gè)統(tǒng)稱,并不單指一個(gè)線程,也并不唯一。后臺(tái)任務(wù)線程包含了Java PA線程、文件操作API、網(wǎng)絡(luò)訪問(wèn)API內(nèi)部實(shí)現(xiàn)等相關(guān)線程。

下面我們結(jié)合測(cè)試代碼,分析這三個(gè)線程的作用和關(guān)系。

JS線程與UI線程的關(guān)系

為了驗(yàn)證JS線程與UI線程的關(guān)系,我們準(zhǔn)備了一個(gè)實(shí)驗(yàn)性質(zhì)的Demo,主要代碼以及運(yùn)行過(guò)程的Log如下:

首先我們?cè)贗DE建立一個(gè)Empty Ablity(JS)模板的HelloWorld工程,在生命周期、按鈕響應(yīng)回調(diào)方法里增加Log以觀察線程情況。剛創(chuàng)建的app.js中Application生命周期默認(rèn)已經(jīng)有Log,無(wú)需額外添加。

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

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


然后在index.hml中增加一個(gè)button以及會(huì)一直進(jìn)行動(dòng)畫的progress組件:

  1. <button id='button1' onclick="onButtonClick">I'm a button</button> 
  2. <progress type="circular"/> 


最后在index.js中增加按鈕點(diǎn)擊響應(yīng)事件以及Log,并且嘗試sleep阻塞js線程:

  1. function sleep(delay) { 
  2. for (var t = Date.now(); Date.now() - t <= delay; ); 
  3. onButtonClick() { 
  4. console.info('onButtonClick begin'); 
  5. sleep(1000); 
  6. console.info('onButtonClick end'); 


將應(yīng)用運(yùn)行起來(lái),點(diǎn)擊兩次按鈕,得到如下Log:

從輸出的Log中,我們可以看到這個(gè)JS FA進(jìn)程號(hào)為22592,也就是說(shuō)UI線程是22592;生命周期回調(diào)以及按鈕響應(yīng)均在24077線程,這個(gè)就是JS線程,所以JS線程與UI線程不是同一個(gè)線程。

并且我們嘗試通過(guò)sleep方法阻塞JS線程,想觀察JS線程阻塞是否會(huì)影響到UI線程的刷新。最終得出的結(jié)論是無(wú)論JS線程sleep多長(zhǎng)時(shí)間,UI界面上的progress組件動(dòng)畫一直會(huì)不斷刷新,按鈕也會(huì)有按壓效果變化,所以我們可以推測(cè)JS線程與UI線程的相互調(diào)用應(yīng)該是通過(guò)某種消息機(jī)制完成的,而不是阻塞式的調(diào)用。

JS線程與后臺(tái)任務(wù)線程的關(guān)系

ACE JS框架提供了JS FA(Feature Ability)調(diào)用Java PA(Particle Ability)的機(jī)制,該機(jī)制提供了一種通道來(lái)傳遞方法調(diào)用、處理數(shù)據(jù)返回以及訂閱事件上報(bào)。通過(guò)以下Demo可以驗(yàn)證 JS 線程與Java PA線程的關(guān)系:

在JS中,我們通過(guò)FeatureAbility.callAbility拉起并調(diào)用了名為一個(gè)類名為ServiceAbility的Java PA,并拿到返回結(jié)果:

  1. var action = {}; 
  2. action.bundleName = 'com.blancwu.test'
  3. action.abilityName = 'com.blancwu.test.ServiceAbility'
  4. action.messageCode = 1001
  5. action.abilityType = 0
  6. action.syncOption = 0
  7.  
  8. console.info('FeatureAbility.callAbility begin' + JSON.stringify(action));FeatureAbility.callAbility(action).then(function (value) { 
  9. console.info('FeatureAbility.callAbility async result ' + JSON.stringify(value)); 
  10. }) 
  11. console.info('FeatureAbility.callAbility end' + JSON.stringify(action)); 

在ServiceAbility的onRemoteRequest中增加Log輸出,并sleep 1秒鐘,以便觀察線程情況與之間關(guān)系:

  1. @Override 
  2. public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException { 
  3. HiLog.info(LABEL_LOG, "onRemoteRequest begin " + code); 
  4. if (code == 1001) { 
  5. try { 
  6. Thread.sleep(1000); 
  7. } catch (InterruptedException e) { 
  8. e.printStackTrace(); 
  9. Map<String, Object> result = new HashMap<String, Object>(); 
  10. result.put("result", 1); 
  11. reply.writeString(ZSONObject.toZSONString(result)); 
  12. HiLog.info(LABEL_LOG, "onRemoteRequest end " + code); 
  13. return super.onRemoteRequest(code, data, reply, option); 


完成以上代碼后,并進(jìn)行執(zhí)行,可得到的Log如下:

我們觀察到本次運(yùn)行主進(jìn)程(UI線程)號(hào)為4133,JS代碼執(zhí)行在JS線程5887,Java PA響應(yīng)onRemoteRequest執(zhí)行在另一個(gè)后臺(tái)任務(wù)線程5837。通過(guò)Log我們看到onRemoteRequst即使阻塞了后臺(tái)任務(wù)線程1s也不會(huì)影響JS線程的并行執(zhí)行以及主線程(UI線程)上動(dòng)畫的刷新,做到了JS線程與后臺(tái)任務(wù)線程異步地執(zhí)行事務(wù)。

JS線程的異步機(jī)制

上面從代碼實(shí)驗(yàn)角度觀察到了JS線程與其他線程的異步關(guān)系,那么JS線程處理來(lái)自其他多個(gè)線程的調(diào)用是怎么實(shí)現(xiàn)的呢?
首先,我們來(lái)看一下傳統(tǒng)瀏覽器環(huán)境下的運(yùn)行機(jī)制:

上圖中,JS線程中的函數(shù)調(diào)用會(huì)存在于棧(stack)中,棧中的函數(shù)可以調(diào)用瀏覽器環(huán)境提供的WebAPIs,包含了DOM、ajax、timeout等API,這些API會(huì)在瀏覽器環(huán)境提供的另外一個(gè)外部線程執(zhí)行,執(zhí)行完成后會(huì)在任務(wù)隊(duì)列(callback queue)中加入對(duì)應(yīng)的回調(diào)事件(如onClick、onLoad、onDone)。

當(dāng)棧中的代碼執(zhí)行完畢,即棧清空后,JS線程又會(huì)通過(guò)event loop取出任務(wù)隊(duì)列中的下一個(gè)任務(wù)進(jìn)行執(zhí)行,以此類推完成整個(gè)程序執(zhí)行。

HarmonyOS ACE開(kāi)發(fā)框架同樣遵循上述最基本的EventLoop調(diào)度機(jī)制,并且提供了更多的機(jī)制和API,讓業(yè)務(wù)邏輯可以在外部線程執(zhí)行,包含了上面提到的Java PA以及異步回調(diào)的系統(tǒng)能力API。其中,異步回調(diào)的系統(tǒng)能力API包含如文件系統(tǒng)操作和網(wǎng)絡(luò)操作等,具體大家可以按照我們實(shí)驗(yàn)Demo的方法去嘗試一下。
● 參考 https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-file-storage-0000000000629445

未來(lái)發(fā)展的展望

目前ACE JS應(yīng)用內(nèi)實(shí)現(xiàn)多線程的最佳方式是通過(guò)混合編程調(diào)用Java PA方式,未來(lái),隨著純JS應(yīng)用越來(lái)越多,只支持單線程的JS ACE框架的異步API并不能解決各種復(fù)雜場(chǎng)景問(wèn)題。

單線程的JS加上異步API能夠很好解決單個(gè)I/O阻塞的問(wèn)題,但是如果遇到大量的I/O事件,比如批刪除大量文件,通過(guò)for循環(huán)發(fā)起了大量異步任務(wù),也會(huì)降低執(zhí)行效率,甚至阻塞其他異步任務(wù)的執(zhí)行。并且如果要使用JS語(yǔ)言開(kāi)發(fā)計(jì)算密集型的任務(wù),也無(wú)法在唯一的JS線程上進(jìn)行。

這時(shí)就需要一個(gè)真正的JS多線程處理機(jī)制了,雖然目前HarmonyOS 2還未支持,但未來(lái)HarmonyOS會(huì)考慮規(guī)劃出與HTML5類似提供支持WebWorker機(jī)制,支持開(kāi)發(fā)出多線程的JS代碼,提供給應(yīng)用開(kāi)發(fā)者更多的發(fā)揮空間。

 

責(zé)任編輯:黃顯東 來(lái)源: 51CTO
相關(guān)推薦

2025-04-24 08:15:00

Redis單線程線程

2025-06-17 00:22:00

2021-01-10 11:21:33

JavaScript語(yǔ)言開(kāi)發(fā)

2009-07-10 09:05:20

SwingWorker

2021-06-11 11:28:22

多線程fork單線程

2019-06-17 14:20:51

Redis數(shù)據(jù)庫(kù)Java

2020-11-09 09:33:37

多線程

2021-08-10 07:00:01

Redis單線程并發(fā)

2010-08-30 08:55:56

JavaScript引

2022-01-04 11:11:32

Redis單線程Reactor

2019-05-06 11:12:18

Redis高并發(fā)單線程

2022-06-22 08:16:29

異步非阻塞框架

2022-07-07 09:12:17

JavaScript線程循環(huán)機(jī)制

2020-10-26 08:55:52

Redis單線程模型

2022-07-18 13:59:43

Redis單線程進(jìn)程

2024-02-26 00:00:00

JavaScript單線程高效

2017-03-06 14:08:38

JavaScript單線程setTimeout

2010-01-28 16:45:44

Android單線程模

2023-10-15 12:23:10

單線程Redis

2012-02-15 10:26:40

JavaJava Socket
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)