Event Loop 是一個很重要的概念茸习,指的是計算機系統(tǒng)的一種運行機制柔逼。
JavaScript語言就采用這種機制,來解決單線程運行帶來的一些問題享钞。
Event Loop
本文參考C. Aaron Cois的《Understanding The Node.js Event Loop》揍诽,解釋什么是Event Loop,以及它與JavaScript語言的單線程模型有何關(guān)系嫩与。
想要理解Event Loop寝姿,就要從程序的運行模式講起。運行以后的程序叫做"進程"(process)划滋,一般情況下饵筑,一個進程一次只能執(zhí)行一個任務(wù)。
如果有很多任務(wù)需要執(zhí)行处坪,不外乎三種解決方法根资。
(1)排隊。因為一個進程一次只能執(zhí)行一個任務(wù)同窘,只好等前面的任務(wù)執(zhí)行完了玄帕,再執(zhí)行后面的任務(wù)。
(2)新建進程想邦。使用fork命令裤纹,為每個任務(wù)新建一個進程。
(3)新建線程丧没。因為進程太耗費資源鹰椒,所以如今的程序往往允許一個進程包含多個線程锡移,由線程去完成任務(wù)。(進程和線程的詳細解釋漆际,請看這里淆珊。)
以JavaScript語言為例,它是一種單線程語言奸汇,所有任務(wù)都在一個線程上完成施符,即采用上面的第一種方法。一旦遇到大量任務(wù)或者遇到一個耗時的任務(wù)擂找,網(wǎng)頁就會出現(xiàn)"假死"戳吝,因為JavaScript停不下來,也就無法響應(yīng)用戶的行為婴洼。
你也許會問骨坑,JavaScript為什么是單線程撼嗓,難道不能實現(xiàn)為多線程嗎?
這跟歷史有關(guān)系粉捻。JavaScript從誕生起就是單線程。原因大概是不想讓瀏覽器變得太復雜肩刃,因為多線程需要共享資源盈包、且有可能修改彼此的運行結(jié)果醇王,對于一種網(wǎng)頁腳本語言來說,這就太復雜了叛氨。后來就約定俗成棘伴,JavaScript為一種單線程語言。(Worker API可以實現(xiàn)多線程仁连,但是JavaScript本身始終是單線程的饭冬。)
如果某個任務(wù)很耗時,比如涉及很多I/O(輸入/輸出)操作伍伤,那么線程的運行大概是下面的樣子。
synchronous mode
上圖的綠色部分是程序的運行時間麦乞,紅色部分是等待時間姐直〗螅可以看到,由于I/O操作很慢插龄,所以這個線程的大部分運行時間都在空等I/O操作的返回結(jié)果均牢。這種運行方式稱為"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)才睹。
如果采用多線程,同時運行多個任務(wù)垮庐,那很可能就是下面這樣坞琴。
synchronous mode
上圖表明置济,多線程不僅占用多倍的系統(tǒng)資源,也閑置多倍的資源护盈,這顯然不合理羞酗。
Event Loop就是為了解決這個問題而提出的。Wikipedia這樣定義:
"Event Loop是一個程序結(jié)構(gòu)欺嗤,用于等待和發(fā)送消息和事件卫枝。(a programming construct that waits for and dispatches events or messages in a program.)"
簡單說,就是在程序中設(shè)置兩個線程:一個負責程序本身的運行吆玖,稱為"主線程"马篮;另一個負責主線程與其他進程(主要是各種I/O操作)的通信浑测,被稱為"Event Loop線程"(可以譯為"消息線程")。
asynchronous mode
上圖主線程的綠色部分掷匠,還是表示運行時間槐雾,而橙色部分表示空閑時間幅狮。每當遇到I/O的時候崇摄,主線程就讓Event Loop線程去通知相應(yīng)的I/O程序慌烧,然后接著往后運行,所以不存在紅色的等待時間厕氨。等到I/O程序完成操作汹粤,Event Loop線程再把結(jié)果返回主線程。主線程就調(diào)用事先設(shè)定的回調(diào)函數(shù)国葬,完成整個任務(wù)。
可以看到接奈,由于多出了橙色的空閑時間序宦,所以主線程得以運行更多的任務(wù)背苦,這就提高了效率。這種運行方式稱為"異步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)疫剃。
這正是JavaScript語言的運行方式硼讽。單線程模型雖然對JavaScript構(gòu)成了很大的限制,但也因此使它具備了其他語言不具備的優(yōu)勢壤躲。如果部署得好备燃,JavaScript程序是不會出現(xiàn)堵塞的并齐,這就是為什么node.js平臺可以用很少的資源,應(yīng)付大流量訪問的原因撕贞。
(完)