HarmonyOS 2提供了兩種應用開(kāi)發(fā)語(yǔ)言:Java和JS。Java線(xiàn)程特性能夠讓多任務(wù)并行,充分利用硬件資源開(kāi)發(fā)出高性能的應用。 而JS卻是一個(gè)單線(xiàn)程語(yǔ)言,無(wú)法像Java一樣創(chuàng )建新的Thread,用JS語(yǔ)言開(kāi)發(fā)是否會(huì )導致硬件資源無(wú)法充分利用的情況呢?
本文給大家介紹“ACE JS的單線(xiàn)程異步機制”就是解決這個(gè)問(wèn)題的。然而,說(shuō)到 “單線(xiàn)程”與“異步”,大家可能會(huì )比較疑惑,因為單線(xiàn)程和異步在概念上是沖突的,單線(xiàn)程無(wú)法做到多任務(wù)并發(fā),也就不會(huì )存在異步這種通信機制。
確實(shí),JS語(yǔ)言本身是無(wú)法實(shí)現異步的,但是ACE JS框架卻提供了多線(xiàn)程的宿主環(huán)境,通過(guò)消息通信機制讓JS語(yǔ)言有了異步的屬性,下面我們來(lái)詳細描述其原理。
ACE開(kāi)發(fā)框架
使用JS開(kāi)發(fā)HarmonyOS應用,使用的開(kāi)發(fā)框架名為ACE(Ability Cross-Platform Environment),該框架適用于手機、平板、智慧屏、智慧表、車(chē)機等設備,具備“一次開(kāi)發(fā),多端部署”的能力。
ACE框架包括應用層(Application)、前端框架層(Framework)、引擎層(Engine)和平臺適配層(Porting Layer),如下圖所示:
●Application
應用層表示開(kāi)發(fā)者使用JS UI框架開(kāi)發(fā)的FA應用,這里的FA應用特指JS FA應用。
●Framework
前端框架層主要完成前端頁(yè)面解析,以及提供MVVM(Model-View-ViewModel)開(kāi)發(fā)模式、頁(yè)面路由機制和自定義組件等能力。
●Engine
引擎層主要提供動(dòng)畫(huà)解析、DOM(Document Object Model)樹(shù)構建、布局計算、渲染命令構建與繪制、事件管理等能力。
●Porting Layer
適配層主要完成對平臺層進(jìn)行抽象,提供抽象接口,可以對接到系統平臺。比如:事件對接、渲染管線(xiàn)對接和系統生命周期對接等。
ACE開(kāi)發(fā)框架的線(xiàn)程模型
每個(gè)HarmonyOS JS應用,都是通過(guò)上圖所示的ACE開(kāi)發(fā)框架進(jìn)行加載渲染的。ACE開(kāi)發(fā)框架包含了JS線(xiàn)程、UI線(xiàn)程、GPU線(xiàn)程、IO線(xiàn)程,并且在A(yíng)CE框架外還會(huì )存在一類(lèi)后臺任務(wù)線(xiàn)程。
其中GPU線(xiàn)程與IO線(xiàn)程主要是ACE框架初始化與頁(yè)面加載渲染的過(guò)程需要的,為ACE框架內部的專(zhuān)有線(xiàn)程,不會(huì )被應用直接操作到,應用不需要特別關(guān)注;UI線(xiàn)程、JS線(xiàn)程和后臺任務(wù)線(xiàn)程會(huì )與應用開(kāi)發(fā)代碼相關(guān),后面著(zhù)重分析這三個(gè)線(xiàn)程的作用和關(guān)系。
●UI線(xiàn)程:負責應用界面的繪制刷新,與應用的進(jìn)程號相同,又叫主線(xiàn)程。如果開(kāi)發(fā)JS+JAVA的混合編程,JAVA PA(Particle Ability)的onStart/onConnect等Ability生命周期回調便是運行在主線(xiàn)程,若在這些生命周期回調上執行耗時(shí)操作則會(huì )導致JS UI的繪制刷新卡住。
●JS線(xiàn)程:應用的JS代碼會(huì )被JS引擎解析執行,并運行在JS線(xiàn)程上,而JS又是單線(xiàn)程語(yǔ)言,所以目前我們工程中看到的所有的JS代碼都會(huì )執行在這個(gè)進(jìn)程下唯一的JS線(xiàn)程上。
●后臺任務(wù)線(xiàn)程:這里是對ACE框架外部的后臺線(xiàn)程的一個(gè)統稱(chēng),并不單指一個(gè)線(xiàn)程,也并不唯一。后臺任務(wù)線(xiàn)程包含了Java PA線(xiàn)程、文件操作API、網(wǎng)絡(luò )訪(fǎng)問(wèn)API內部實(shí)現等相關(guān)線(xiàn)程。
下面我們結合測試代碼來(lái)看一下這3個(gè)線(xiàn)程之間的關(guān)系。
JS線(xiàn)程與UI線(xiàn)程的關(guān)系
為了驗證JS線(xiàn)程與UI線(xiàn)程的關(guān)系,我們準備了一個(gè)實(shí)驗性質(zhì)的Demo,主要代碼以及運行過(guò)程的Log如下:
首先我們在IDE建立一個(gè)Empty Ablity(JS)模板的HelloWorld工程,在生命周期、按鈕響應回調方法里增加Log以觀(guān)察線(xiàn)程情況。剛創(chuàng )建的app.js中Application生命周期默認已經(jīng)有Log,無(wú)需額外添加。
我們只需要在主界面index.js文件中onInit增加日志:
console.info('page.default onInit');
然后在index.hml中增加一個(gè)button以及會(huì )一直進(jìn)行動(dòng)畫(huà)的progress組件:
<button id='button1' a button</button>
<progress type="circular"/>
最后在index.js中增加按鈕點(diǎn)擊響應事件以及Log,并且嘗試sleep阻塞js線(xiàn)程:
function sleep(delay) {
for (var t = Date.now(); Date.now() - t <= delay; );
}
onButtonClick() {
console.info('onButtonClick begin');
sleep(1000);
console.info('onButtonClick end');
}
將應用運行起來(lái),點(diǎn)擊兩次按鈕,得到如下Log:
從輸出的Log中,我們可以看到這個(gè)JS FA進(jìn)程號為22592,也就是說(shuō)UI線(xiàn)程是22592;生命周期回調以及按鈕響應均在24077線(xiàn)程,這個(gè)就是JS線(xiàn)程,所以JS線(xiàn)程與UI線(xiàn)程不是同一個(gè)線(xiàn)程。
并且我們嘗試通過(guò)sleep方法阻塞JS線(xiàn)程,想觀(guān)察JS線(xiàn)程阻塞是否會(huì )影響到UI線(xiàn)程的刷新。最終得出的結論是無(wú)論JS線(xiàn)程sleep多長(cháng)時(shí)間,UI界面上的progress組件動(dòng)畫(huà)一直會(huì )不斷刷新,按鈕也會(huì )有按壓效果變化,所以我們可以推測JS線(xiàn)程與UI線(xiàn)程的相互調用應該是通過(guò)某種消息機制完成的,而不是阻塞式的調用。
JS線(xiàn)程與后臺任務(wù)線(xiàn)程的關(guān)系
ACE JS框架提供了JS FA(Feature Ability)調用Java PA(Particle Ability)的機制,該機制提供了一種通道來(lái)傳遞方法調用、處理數據返回以及訂閱事件上報。我們同樣制作一個(gè)Demo來(lái)驗證JS線(xiàn)程與Java PA線(xiàn)程的關(guān)系:
在JS中,我們通過(guò)FeatureAbility.callAbility拉起并調用了名為一個(gè)類(lèi)名為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秒鐘,以便觀(guān)察線(xiàn)程情況與之間關(guān)系:
@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<String, Object> result = new HashMap<String, Object>();
result.put("result", 1);
reply.writeString(ZSONObject.toZSONString(result));
}
HiLog.info(LABEL_LOG, "onRemoteRequest end " + code);
return super.onRemoteRequest(code, data, reply, option);
}
以上代碼完成后,我們進(jìn)行執行,得到的Log如下:
我們觀(guān)察到本次運行主進(jìn)程(UI線(xiàn)程)號為4133,JS代碼執行在JS線(xiàn)程5887,Java PA響應onRemoteRequest執行在另一個(gè)后臺任務(wù)線(xiàn)程5837。通過(guò)Log我們看到onRemoteRequst即使阻塞了后臺任務(wù)線(xiàn)程1s也不會(huì )影響JS線(xiàn)程的并行執行以及主線(xiàn)程(UI線(xiàn)程)上動(dòng)畫(huà)的刷新,做到了JS線(xiàn)程與后臺任務(wù)線(xiàn)程異步地執行事務(wù)。
JS線(xiàn)程的異步機制
上面從代碼實(shí)驗角度觀(guān)察到了JS線(xiàn)程與其他線(xiàn)程的異步關(guān)系,那么JS線(xiàn)程是怎么處理來(lái)自其他多個(gè)線(xiàn)程的調用的呢?我們先來(lái)看一下傳統的瀏覽器環(huán)境下的機制:
上圖中,JS線(xiàn)程中的函數調用會(huì )存在于棧(stack)中,棧中的函數可以調用瀏覽器環(huán)境提供的WebAPIs,包含了DOM、ajax、timeout等API,這些API會(huì )在瀏覽器環(huán)境提供的另外一個(gè)外部線(xiàn)程執行,執行完成后會(huì )在任務(wù)隊列(callback queue)中加入對應的回調事件(如onClick、onLoad、onDone)。當棧中的代碼執行完畢,即棧清空后,JS線(xiàn)程又會(huì )通過(guò)event loop取出任務(wù)隊列中的下一個(gè)任務(wù)進(jìn)行執行,以此類(lèi)推完成整個(gè)的程序執行。更具體的機制可以去看阮一峰老師介紹JS EventLoop的文章:
● JS EventLoop介紹
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
HarmonyOS ACE開(kāi)發(fā)框架同樣遵循上述最基本的EventLoop調度機制,并且提供了更多的機制和API,讓業(yè)務(wù)邏輯可以在外部線(xiàn)程執行,包含了上面提到的Java PA以及異步回調的系統能力API。其中,異步回調的系統能力API包含如文件系統操作和網(wǎng)絡(luò )操作等,具體大家可以按照我們實(shí)驗Demo的方法去嘗試一下。
● 參考
https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-file-storage-0000000000629445
未來(lái)發(fā)展的展望
目前ACE JS應用內實(shí)現多線(xiàn)程的最佳方式是通過(guò)混合編程調用Java PA方式,但未來(lái)純JS應用一定會(huì )越來(lái)越多,那么,只支持單線(xiàn)程的JS ACE框架的異步API能解決各種復雜場(chǎng)景的問(wèn)題嗎?
單線(xiàn)程的JS加上異步API能夠很好解決單個(gè)I/O阻塞的問(wèn)題,但是如果遇到大量的I/O事件,比如批刪除大量文件,通過(guò)for循環(huán)發(fā)起了大量異步任務(wù),也會(huì )降低執行效率,甚至阻塞其他異步任務(wù)的執行。并且如果要使用JS語(yǔ)言開(kāi)發(fā)計算密集型的任務(wù),也無(wú)法在唯一的JS線(xiàn)程上進(jìn)行。
這時(shí)就需要一個(gè)真正的JS多線(xiàn)程處理機制了,雖然目前HarmonyOS 2還未支持,但未來(lái)HarmonyOS會(huì )考慮規劃出與HTML5類(lèi)似提供支持WebWorker機制,支持開(kāi)發(fā)出多線(xiàn)程的JS代碼,提供給應用開(kāi)發(fā)者更多的發(fā)揮空間。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站