亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        基于Node.js的JavaScript并發(fā)控制流框架

        2015-11-19 03:54:04李軼
        江漢大學學報(自然科學版) 2015年2期
        關鍵詞:緩沖區(qū)計數(shù)器調用

        李軼

        (江漢大學 數(shù)學與計算機科學學院,湖北 武漢 430056)

        基于Node.js的JavaScript并發(fā)控制流框架

        李軼

        (江漢大學 數(shù)學與計算機科學學院,湖北 武漢 430056)

        Node.js因其異步I/O的特性,非常適合于服務器端的JavaScript開發(fā)。然而為實現(xiàn)此環(huán)境下異步I/O的并發(fā)控制,開發(fā)者不得不手工編寫繁瑣的代碼,因而給開發(fā)者造成了障礙。以并發(fā)計數(shù)器為基礎,可以設計一個并發(fā)控制流框架。該框架以直觀的調用形式,實現(xiàn)了異步I/O間的并發(fā)控制;其不僅有助于Node.js環(huán)境下的JavaScript開發(fā),更提高了開發(fā)者的開發(fā)效率。

        異步I/O;并發(fā);同步;并發(fā)計數(shù)器;JavaScript

        0 引言

        時至今日,JavaScript的應用領域早已從前端的Web瀏覽器,延伸到后臺服務器。作為一個基于V8[1]引擎的服務器端JavaScript環(huán)境,Node.js[2]從發(fā)布之初就備受矚目。Node.js以V8引擎的輕量、高效、快速為基礎,同時又提供了基于事件驅動的異步I/O(Asynchronous I/O)特性[3],使其非常適合于開發(fā)不同規(guī)模的數(shù)據(jù)密集型、實時型分布式應用。

        1 異步I/O與并發(fā)控制

        異步I/O又稱為非阻塞式I/O,它是Node.js具有的獨特特性。不同于傳統(tǒng)的每客戶一服務線程的服務器架構,Node.js是單線程腳本環(huán)境。其核心思想是用一個服務線程應對多個客戶請求。當服務進程響應客戶請求執(zhí)行I/O操作(如網(wǎng)絡I/O、文件I/O或數(shù)據(jù)庫I/O等)時,異步I/O可避免因服務線程被I/O操作阻塞而無法響應其他用戶請求的情況。因此,異步I/O不僅避免了多服務線程對服務器資源的過多占用,又提高了服務線程的執(zhí)行效率,從而使一個服務線程就能應對大量的并發(fā)客戶請求。

        在調用異步I/O函數(shù)時,通常都需要指定一個或多個回調函數(shù)作為其參數(shù)。這是因為異步I/O的非阻塞特性,異步函數(shù)在調用后會立即返回。當I/O操作完成后,需要回調函數(shù)通知調用者I/O操作完成。此外,回調函數(shù)可能還帶有若干參數(shù),其是I/O操作所返回的數(shù)據(jù)。

        有時為實現(xiàn)某一特定功能或為提高程序執(zhí)行效率,多個異步I/O之間既需要并發(fā)(concurrency)[4],又需要在彼此間進行同步(synchronization)[5]。例如,有3個異步I/O可并發(fā)執(zhí)行,但同時要求3個異步I/O全部完成后,才能執(zhí)行下一步操作。此時,最通常的辦法是通過設置并檢查多個標志位來實現(xiàn)。假設3個異步I/O函數(shù)分別為ioA、ioB和ioC。為達成此目標,需要設置3個I/O標志位,分別為:tagA、tagB、tagC,并將其初值設為false。此后,在每個I/O函數(shù)的異步回調中,再將該標識位置設為true,并檢查其余標志位。若所有標志位全為true,則表明并發(fā)全部完成,可進行下一步操作。例程如下:

        由此可以看出,這種復雜繁瑣的代碼,雖然在執(zhí)行邏輯上正確,但是在程序編寫,代碼可讀性及程序調試上存在諸多不便。特別是在開發(fā)較為復雜邏輯的系統(tǒng)時,隨著標志位的增加,復雜繁瑣的代碼已經(jīng)成為開發(fā)者的阻礙。因此需要一種方法,將復雜的代碼簡化;也就是說需要一種并發(fā)控制流框架,實現(xiàn)異步I/O間的并發(fā)控制。

        2 任務對象與并發(fā)任務緩沖區(qū)

        為解決上述問題,可考慮應用并發(fā)計數(shù)器機制。每個異步I/O的調用,可封裝成為一個任務對象;依據(jù)任務對象的數(shù)目,設置并發(fā)計數(shù)器的初值。當某個任務完成時(即當其I/O函數(shù)的回調函數(shù)被調用時)將并發(fā)計數(shù)器值減1;若并發(fā)計數(shù)器的值減1后為0,則表明所有并發(fā)任務均執(zhí)行完畢。如此,多個異步I/O間的并發(fā)控制就可抽象為任務及并發(fā)任務計數(shù)器的相關操作。

        對異步I/O任務而言,其具體屬性包括:任務名、任務函數(shù)和任務參數(shù);此外,還需要為多個并發(fā)任務建立一個并發(fā)緩沖區(qū),其狀態(tài)圖如圖1所示。并發(fā)緩沖區(qū)創(chuàng)建后為就緒狀態(tài),當需要同步的多個并發(fā)任務加入緩沖區(qū)后,就可啟動并發(fā)同步過程。由于任務函數(shù)中包含了異步調用,任務函數(shù)執(zhí)行完后會立即返回,但此時并不能認為該任務完成,而是在未來某個時刻,在該任務中的異步回調得到執(zhí)行后,才可認為該任務執(zhí)行完畢。在該任務完成后,并發(fā)計數(shù)器的值會自動減1,并檢查其值。若為0則表明所有并發(fā)任務均執(zhí)行完畢,緩沖區(qū)返回就緒態(tài)。此外,當某任務執(zhí)行出錯時,緩沖區(qū)進入終止狀態(tài);當某任務超時時,緩沖區(qū)進入超時狀態(tài)。在此兩種狀態(tài)下,都可重新將緩沖區(qū)復位為就緒態(tài)。

        圖1 并發(fā)任務緩沖區(qū)狀態(tài)圖Fig.1 State chart of concurrent task buffer

        3 基于計數(shù)器的并發(fā)控制流框架

        以上述討論作為基礎,可構造一個以并發(fā)計數(shù)器為核心的并發(fā)控制流框架。該框架以Node.js的模塊形式為用戶提供調用接口,模塊命名為“concurrentBuf”。另外,由于Node.js為單線程腳本環(huán)境,因此也無需考慮計數(shù)器操作的線程安全問題。

        3.1 模塊接口規(guī)范(Module interface specifications)

        3.1.1 create函數(shù) 模塊的唯一調用接口為函數(shù)“create”,該函數(shù)用于創(chuàng)建一個新的并發(fā)緩沖區(qū)對象。其函數(shù)聲明為:function create(name,timeoutMs)。

        其中參數(shù)name為并發(fā)緩沖區(qū)的名稱;timeoutMs為并發(fā)任務超時毫秒數(shù),即在所有任務中,最長的任務耗時不得超過timeoutMs的毫秒數(shù);否則認為并發(fā)同步超時。

        3.1.2 并發(fā)任務緩沖區(qū)對象的方法 并發(fā)任務緩沖區(qū)對象有如下方法。

        1)push方法

        該方法將一個并發(fā)任務放入緩沖區(qū)。

        其方法聲明為:push(name,task,argsAry)。

        其中參數(shù)name為并發(fā)任務名;task為任務函數(shù);argsAry為函數(shù)task的參數(shù)數(shù)組,其中每個元素為一個參數(shù)對象。參數(shù)對象具有屬性type和屬性value;其中type屬性為字符串類型,其用于指示參數(shù)的類型。特別需要注意的是,參數(shù)的類型除包括JavaScript標準類型之外,還包括類型“callback”,其表示該參數(shù)為一回調函數(shù);屬性value則用來存儲實際的參數(shù)值。

        2)reset方法

        該方法將并發(fā)任務緩沖區(qū)重新復位,無需任何參數(shù)。

        3)start方法

        該方法啟動并發(fā)緩沖區(qū)中的所有任務,無需任何參數(shù)。

        4)onError方法

        其聲明格式為:onError(errorCb)。

        該方法用于指定當某個并發(fā)任務發(fā)生執(zhí)行錯誤時的事件處理函數(shù),通過參數(shù)errorCB指定。該方法返回并發(fā)緩沖區(qū)本身的引用。錯誤事件處理函數(shù)errorCb的函數(shù)聲明為:function(taskName,e)。其中參數(shù)taskName為發(fā)生錯誤的任務名;參數(shù)e為錯誤對象。

        5)onComplete方法

        其聲明格式為:onComplete(cb)。

        該方法用于指定并發(fā)任務全部完成時的事件處理函數(shù),通過參數(shù)cb指定。

        6)onTimeout方法

        其聲明格式為:onTimeout(cb)。

        該方法用于指定并發(fā)任務超時的事件處理函數(shù),通過參數(shù)cb指定。

        3.1.3 并發(fā)任務緩沖區(qū)對象的事件 并發(fā)任務緩沖區(qū)對象有如下事件。

        1)error事件

        當某個并發(fā)任務執(zhí)行中發(fā)生錯誤時,該事件被觸發(fā)。該事件的處理函數(shù)聲明為:function(taskName,e),由緩沖區(qū)對象的onError方法指定。

        其中參數(shù)taskName為發(fā)生錯誤的任務名,參數(shù)e為錯誤對象,其具有的屬性包括:code,message和stack;其中code屬性為錯誤代碼;message屬性為出錯信息字符串;stack屬性為出錯時的函數(shù)調用棧。

        2)complete事件

        當所有并發(fā)任務完成時,該事件被觸發(fā)。該事件處理函數(shù)由緩沖區(qū)對象的onComplete方法進行指定,該事件無其他參數(shù)。

        3)timeout事件

        當并發(fā)任務同步超時時,該事件被觸發(fā)。該事件處理函數(shù)由緩沖區(qū)對象的onComplete方法進行指定,該事件無其他參數(shù)。

        3.2 模塊實現(xiàn)

        3.2.1 create函數(shù) 函數(shù)create用于創(chuàng)建一個并發(fā)緩沖對象,此函數(shù)也是模塊對外暴露的唯一接口函數(shù)。其函數(shù)聲明為:function create(name,timeoutMs)。其中參數(shù)name為并發(fā)緩沖區(qū)名稱;timeoutMs為任務超時毫秒數(shù)。函數(shù)的返回值,即為并發(fā)緩沖區(qū)對象,其具有的方法和事件已經(jīng)在上述模塊接口規(guī)范中進行了說明。

        3.2.2 并發(fā)任務計數(shù)器 本框架使用create函數(shù)的局部變量pCunter存儲引用計數(shù)值。由于閉包(closure)[6]的作用,pCunter受到保護,防止了其從外部被訪問,并具有和緩沖區(qū)對象相同的生存期。

        3.2.3 并發(fā)任務存儲 本框架使用create函數(shù)的局部變量pBuffer存儲任務隊列。pBuffer為一數(shù)組,其中的每個成員,都是一個任務對象。任務對象具有3個屬性:fName、fn和argary。其中fName為任務名;fn為任務函數(shù);argary為任務函數(shù)參數(shù)值數(shù)組。

        同樣由于閉包的作用,pBuffer受到保護,防止了其從外部被訪問,并具有和緩沖區(qū)對象相同的生存期。

        3.2.4 并發(fā)任務緩沖區(qū)狀態(tài) 本框架使用模塊全局對象STATES,枚舉緩沖區(qū)的所有狀態(tài)。緩沖區(qū)對象的狀態(tài)轉換,如圖2所示。對象STATES包含以下屬性:ready、running、terminated和expired。屬性ready表示緩沖區(qū)就緒,其值為0;屬性running表示并發(fā)任務運行中,其值為1;屬性terminated表示緩沖區(qū)因某任務執(zhí)行異常而終止,其值為2;屬性expired表示任務執(zhí)行超時導致緩沖區(qū)并發(fā)同步超時,其值為3。

        圖2 并發(fā)任務緩沖區(qū)對象狀態(tài)圖Fig.2 Object state chart of concurrent task buffer

        對于緩沖區(qū)狀態(tài)的保存,則由模塊函數(shù)create的局部變量pState存儲。

        3.2.5 并發(fā)任務的加入 并發(fā)任務的加入由緩沖區(qū)對象的push方法完成,具體描述已在模塊接口定義規(guī)范中進行了說明,執(zhí)行流程較為簡單。push方法首先判斷緩沖區(qū)的當前狀態(tài),若不處于就緒態(tài),則方法直接返回;否則,push方法將任務名、任務函數(shù)以及任務參數(shù)數(shù)組封裝成為一個任務對象,并將之追加到pBuffer數(shù)組中。

        3.2.6 任務對象的封裝 如上所述,push方法會將任務名、任務函數(shù)以及任務參數(shù)數(shù)組封裝成為一任務對象。在對任務進行封裝時,有兩個需要注意的地方。

        首先,為捕獲任務函數(shù)中可能發(fā)生的執(zhí)行異常,需要對任務函數(shù)進行二次封裝。即在原任務函數(shù)的基礎上構造出一個新的函數(shù),如圖3所示。此函數(shù)通過try…catch語句調用原任務函數(shù),若發(fā)生異常,則在catch子句中終止超時計時器,并改變緩沖區(qū)狀態(tài)為終止態(tài)(STATUS.terminated),然后觸發(fā)緩沖區(qū)的error事件,并將捕獲的錯誤對象交由用戶進行處理。

        其次,為保證并發(fā)引用計數(shù)器在任務完成后能自動減1,還需要對任務參數(shù)數(shù)組中的回調函數(shù)進行二次封裝。圖4為任務回調的二次封裝函數(shù)執(zhí)行流程。二次封裝函數(shù)首先檢查當前緩沖區(qū)狀態(tài);若為運行態(tài)(STATUS.running),則將計數(shù)器減1,然后執(zhí)行用戶的任務回調函數(shù)。在用戶回調函數(shù)返回后,檢查計數(shù)器的值,若為0則表示所有并發(fā)任務均已完成,因此終止超時計時器,并設置緩沖區(qū)狀態(tài)為就緒態(tài),最后觸發(fā)緩沖區(qū)complete事件;若當前緩沖區(qū)狀態(tài)為非運行態(tài),說明有某任務執(zhí)行異?;虺瑫r,并發(fā)執(zhí)行失敗,因此直接返回即可。

        圖3 任務函數(shù)的二次封裝函數(shù)執(zhí)行流程圖Fig.3 Executive flow chart of the second wrapper function of task function

        圖4 任務回調的二次封裝函數(shù)執(zhí)行流程Fig.4 Flow chart of the second wrapper function of task callback

        由此可見,任務對象中的任務函數(shù)及參數(shù)數(shù)組中的回調函數(shù)都是其原函數(shù)的二次封裝函數(shù)。

        3.2.7 并發(fā)任務的啟動 并發(fā)任務的啟動由并發(fā)緩沖區(qū)對象的start方法完成。該方法的執(zhí)行流程較為簡單,首先啟動一個任務超時計時器,并設置好其超時回調函數(shù);然后設置引用計數(shù)器pCunter的初值為pBuffer數(shù)組長度,并設置緩沖區(qū)狀態(tài)為運行態(tài)。最后,依次調用pBuffer數(shù)組中每個任務對象的任務函數(shù)。

        3.2.8 并發(fā)任務緩沖區(qū)復位 并發(fā)緩沖區(qū)復位由并發(fā)緩沖區(qū)對象的reset方法實現(xiàn),其執(zhí)行流程較為簡單。首先檢查當前隊列狀態(tài)是否為終止態(tài)或超時態(tài)。若是,則清空pBuffer數(shù)組并更改狀態(tài)為就緒態(tài)(STATUS.ready)。

        3.3 模塊接口導出

        本模塊的唯一導出接口為函數(shù)create,通過Node.js的模塊對象module的exports屬性進行導出,示例如下:

        module.exports={"create":create};

        4 示例

        以一個簡單的實例演示本框架的使用方法。假設有兩個文件讀取操作,分別為文件A.txt和B.txt,需要并發(fā)控制完成,示例如下:

        程序首先通過require函數(shù),分別獲得并發(fā)同步模塊parallelBuffer和Node.js的文件系統(tǒng)模塊fs。接著調用parallelBuffer的create函數(shù),創(chuàng)建一個并發(fā)同步緩沖區(qū)buf;通過指定timeoutMs參數(shù)為5 000設定任務的最長超時為5 000 ms;接著調用其onError方法,onTimeout方法和onComplete方法,分別指定了任務在出錯、超時和所有任務完成時的事件處理函數(shù)。

        接下來,通過緩沖區(qū)對象的push方法,添加了兩個并發(fā)任務"read_fileA"及"read_fileB";其任務函數(shù)通過Node.js的fs文件系統(tǒng)模塊,分別讀取文件A.txt和文件B.txt的內容。任務函數(shù)的調用參數(shù),被封裝為1個數(shù)組;本例中的任務函數(shù)需要2個參數(shù),因此其參數(shù)數(shù)組包含2個元素,分別為文件名以及文件讀取完畢的回調函數(shù)。

        最后,程序通過緩沖區(qū)對象的start方法啟動并發(fā)任務。若所有并發(fā)任務執(zhí)行無誤,則程序將在控制臺輸出“所有任務并發(fā)同步完成!”。

        5 結語

        通過并發(fā)計數(shù)器的應用,在Node.js環(huán)境下成功地設計了一個并發(fā)控制流框架。解決了因多個異步I/O并發(fā)控制所導致的代碼繁瑣、邏輯復雜等的問題??蚣茉谠O計上簡潔易用,語義明確清晰,代碼可讀性強,符合開發(fā)者的一般邏輯;同時又采用純JavaScript實現(xiàn),不依賴第三方模塊或組件,具有較好的通用性,稍加修改就能適用于各種JavaScript環(huán)境。

        [1]WIKIPEDIA.V8(JavaScript engine)[EB/OL].(2014-6-23)[2014-9-10]http://en.wikipedia.org/wiki/V8_(JavaScript_engine).

        [2]WIKIPEDIA.Node.js[EB/OL].(2014-7-10)[2014-9-10]http://en.wikipedia.org/wiki/Node.js.

        [3]WIKIPEDIA.Asynchronous I/O[EB/OL].(2014-6-11)[2014-9-10]http://en.wikipedia.org/wiki/Asynchronous_I/O.

        [4]WIKIPEDIA.Concurrency(computer science)[EB/OL].(2014-10-11)[2014-10-11]http://en.wikipedia.org/wiki/Concurrency_(computer_science).

        [5]WIKIPEDIA.Synchronization(computer science)[EB/OL].(2014-10-15)[2014-10-15]http://en.wikipedia.org/wiki/Synchronization_(computer_science).

        [6]WIKIPEDIA.Closure(computer science)[EB/OL].(2014-10-17)[2014-10-17]http://en.wikipedia.org/wiki/Closure_(computer_programming).

        [7]BURNHAM T.JavaScript異步編程:設計快速響應的網(wǎng)絡應用[M].北京:人民郵電出版社,2013.

        (責任編輯:范建鳳)

        JavaScript Concurrent Flow-Control Framework Based on Node.js

        LI Yi
        (School of Mathematics and Computer Science,Jianghan University,Wuhan 430056,Hubei,China)

        Because of the asynchronous characteristic of I/O,Node.js is quite suitable for developing server-side JavaScript applications.To implement concurrent asynchronous I/O control,developers have to write tedious code manually,it becomes a barrier to developers.Based on the concurrent counter,a concurrent flow-control framework can be constructed.The framework achieved concurrent control between multiple asynchronous I/O in a direct viewing way.Thus,it benefits server-side JavaScript developments and also promotes the efficiency of development.

        asynchronous I/O;concurrency;synchronization;concurrent counter;JavaScript

        TP393.01

        A

        1673-0143(2015)02-0170-07

        10.16389/j.cnki.cn42-1737/n.2015.02.013

        2014-10-27

        李 軼(1976—),男,實驗員,碩士,研究方向:網(wǎng)絡管理。

        猜你喜歡
        緩沖區(qū)計數(shù)器調用
        嵌入式系統(tǒng)環(huán)形緩沖區(qū)快速讀寫方法的設計與實現(xiàn)
        采用虛擬計數(shù)器的電子式膜式燃氣表
        煤氣與熱力(2022年2期)2022-03-09 06:29:30
        核電項目物項調用管理的應用研究
        LabWindows/CVI下基于ActiveX技術的Excel調用
        測控技術(2018年5期)2018-12-09 09:04:46
        基于系統(tǒng)調用的惡意軟件檢測技術研究
        計數(shù)器競爭冒險及其處理的仿真分析
        關鍵鏈技術緩沖區(qū)的確定方法研究
        任意N進制計數(shù)器的設計方法
        河南科技(2014年10期)2014-02-27 14:09:30
        基于單片機的仰臥起坐計數(shù)器
        利用RFC技術實現(xiàn)SAP系統(tǒng)接口通信
        亚洲激情视频在线观看a五月| 精品国产黑色丝袜高跟鞋| 久久久久亚洲精品美女| 中文字幕高清一区二区| 青青草视频在线观看色| 色综合色狠狠天天综合色| 国产最新网站| 蜜桃视频中文字幕一区二区三区| 国产av在线观看一区二区三区 | 亚洲a无码综合a国产av中文| 欧美粗大猛烈老熟妇| 久久国产热精品波多野结衣av| 综合图区亚洲偷自拍熟女| 日韩熟女系列中文字幕| 天天夜碰日日摸日日澡| 亚洲欧美在线观看一区二区| 天天综合色中文字幕在线视频 | 日本美女性亚洲精品黄色| 新婚少妇无套内谢国语播放 | 国产一区二区三区在线观看免费| 在线亚洲AV不卡一区二区| 国产午夜福利小视频在线观看| 成人欧美一区二区三区在线| 少妇真实被内射视频三四区| 国产精品久久久久久52avav| 精品在免费线中文字幕久久| 毛茸茸的女性外淫小视频| 永久亚洲成a人片777777| 激情欧美日韩一区二区| 香蕉网站在线| 91麻豆精品激情在线观最新| 国产成人a级毛片| 失禁大喷潮在线播放| 久久婷婷国产综合精品| 白色月光免费观看完整版| 一区二区三区国产在线视频| 轻点好疼好大好爽视频| 在线观看av中文字幕不卡| av有码在线一区二区| 日本饥渴人妻欲求不满| 成人综合网亚洲伊人|