事件驅(qū)動(dòng)和異步IO通常,我們寫服務(wù)器處理模型的程序時(shí),有以下幾種模型: (1)每收到一個(gè)請求,創(chuàng)建一個(gè)新的進(jìn)程,來處理該請求; (2)每收到一個(gè)請求,創(chuàng)建一個(gè)新的線程,來處理該請求; (3)每收到一個(gè)請求,放入一個(gè)事件列表,讓主進(jìn)程通過非阻塞I/O方式來處理請求 上面的幾種方式,各有千秋, 第(1)中方法,由于創(chuàng)建新的進(jìn)程的開銷比較大,所以,會(huì)導(dǎo)致服務(wù)器性能比較差,但實(shí)現(xiàn)比較簡單。 第(2)種方式,由于要涉及到線程的同步,有可能會(huì)面臨死鎖等問題。 第(3)種方式,在寫應(yīng)用程序代碼時(shí),邏輯比前面兩種都復(fù)雜。 綜合考慮各方面因素,一般普遍認(rèn)為第(3)種方式是大多數(shù)網(wǎng)絡(luò)服務(wù)器采用的方式 看圖說話講事件驅(qū)動(dòng)模型在UI編程中,常常要對鼠標(biāo)點(diǎn)擊進(jìn)行相應(yīng),首先如何獲得鼠標(biāo)點(diǎn)擊呢?
事件驅(qū)動(dòng)編程是一種編程范式,這里程序的執(zhí)行流由外部事件來決定。它的特點(diǎn)是包含一個(gè)事件循環(huán),當(dāng)外部事件發(fā)生時(shí)使用回調(diào)機(jī)制來觸發(fā)相應(yīng)的處理。另外兩種常見的編程范式是(單線程)同步以及多線程編程。 讓我們用例子來比較和對比一下單線程、多線程以及事件驅(qū)動(dòng)編程模型。下圖展示了隨著時(shí)間的推移,這三種模式下程序所做的工作。這個(gè)程序有3個(gè)任務(wù)需要完成,每個(gè)任務(wù)都在等待I/O操作時(shí)阻塞自身。阻塞在I/O操作上所花費(fèi)的時(shí)間已經(jīng)用灰色框標(biāo)示出來了。
在單線程同步模型中,任務(wù)按照順序執(zhí)行。如果某個(gè)任務(wù)因?yàn)镮/O而阻塞,其他所有的任務(wù)都必須等待,直到它完成之后它們才能依次執(zhí)行。這種明確的執(zhí)行順序和串行化處理的行為是很容易推斷得出的。如果任務(wù)之間并沒有互相依賴的關(guān)系,但仍然需要互相等待的話這就使得程序不必要的降低了運(yùn)行速度。 在多線程版本中,這3個(gè)任務(wù)分別在獨(dú)立的線程中執(zhí)行。這些線程由操作系統(tǒng)來管理,在多處理器系統(tǒng)上可以并行處理,或者在單處理器系統(tǒng)上交錯(cuò)執(zhí)行。這使得當(dāng)某個(gè)線程阻塞在某個(gè)資源的同時(shí)其他線程得以繼續(xù)執(zhí)行。與完成類似功能的同步程序相比,這種方式更有效率,但程序員必須寫代碼來保護(hù)共享資源,防止其被多個(gè)線程同時(shí)訪問。多線程程序更加難以推斷,因?yàn)檫@類程序不得不通過線程同步機(jī)制如鎖、可重入函數(shù)、線程局部存儲或者其他機(jī)制來處理線程安全問題,如果實(shí)現(xiàn)不當(dāng)就會(huì)導(dǎo)致出現(xiàn)微妙且令人痛不欲生的bug。 在事件驅(qū)動(dòng)版本的程序中,3個(gè)任務(wù)交錯(cuò)執(zhí)行,但仍然在一個(gè)單獨(dú)的線程控制中。當(dāng)處理I/O或者其他昂貴的操作時(shí),注冊一個(gè)回調(diào)到事件循環(huán)中,然后當(dāng)I/O操作完成時(shí)繼續(xù)執(zhí)行。回調(diào)描述了該如何處理某個(gè)事件。事件循環(huán)輪詢所有的事件,當(dāng)事件到來時(shí)將它們分配給等待處理事件的回調(diào)函數(shù)。這種方式讓程序盡可能的得以執(zhí)行而不需要用到額外的線程。事件驅(qū)動(dòng)型程序比多線程程序更容易推斷出行為,因?yàn)槌绦騿T不需要關(guān)心線程安全問題。 當(dāng)我們面對如下的環(huán)境時(shí),事件驅(qū)動(dòng)模型通常是一個(gè)好的選擇:
當(dāng)應(yīng)用程序需要在任務(wù)間共享可變的數(shù)據(jù)時(shí),這也是一個(gè)不錯(cuò)的選擇,因?yàn)檫@里不需要采用同步處理。 網(wǎng)絡(luò)應(yīng)用程序通常都有上述這些特點(diǎn),這使得它們能夠很好的契合事件驅(qū)動(dòng)編程模型。 |
|