事件驅動編程

1、 什麼是事件驅動

所謂事件驅動,簡單地說就是你點什麼按鈕(即產生什麼事件),電腦執行什麼操作(即調用什麼函數).當然事件不僅限於用戶的操作. 事件驅動的核心自然是事件。

從事件角度說,事件驅動程序的基本結構是由一個事件收集器、一個事件發送器和一個事件處理器組成。

事件收集器專門負責收集所有事件,包括來自用戶的(如鼠標、鍵盤事件等)、來自硬件的(如時鐘事件等)和來自軟件的(如操作系統、應用程序本身等)。事件發送器負責將收集器收集到的事件分發到目標對象中。事件處理器做具體的事件響應工作,它往往要到實現階段才完全確定。

2、 為什麼要使用事件驅動

事件驅動編程是一種編程範式,這裡程序的執行流由外部事件來決定。它的特點是包含一個事件循環,當外部事件發生時使用回調機制來觸發相應的處理。另外兩種常見的編程範式是(單線程)同步以及多線程編程。

讓我們用例子來比較和對比一下單線程、多線程以及事件驅動編程模型。下圖展示了隨著時間的推移,這三種模式下程序所做的工作。這個程序有3個任務需要完成,每個任務都在等待I/O操作時阻塞自身。阻塞在I/O操作上所花費的時間已經用灰色框標示出來了。


事件驅動編程


在單線程同步模型中,任務按照順序執行。如果某個任務因為I/O而阻塞,其他所有的任務都必須等待,直到它完成之後它們才能依次執行。這種明確的執行順序和串行化處理的行為是很容易推斷得出的。如果任務之間並沒有互相依賴的關係,但仍然需要互相等待的話這就使得程序不必要的降低了運行速度。

在多線程版本中,這3個任務分別在獨立的線程中執行。這些線程由操作系統來管理,在多處理器系統上可以並行處理,或者在單處理器系統上交錯執行。這使得當某個線程阻塞在某個資源的同時其他線程得以繼續執行。與完成類似功能的同步程序相比,這種方式更有效率,但程序員必須寫代碼來保護共享資源,防止其被多個線程同時訪問。多線程程序更加難以推斷,因為這類程序不得不通過線程同步機制如鎖、可重入函數、線程局部存儲或者其他機制來處理線程安全問題。

在事件驅動版本的程序中,3個任務交錯執行,但仍然在一個單獨的線程控制中。當處理I/O或者其他操作時,註冊一個回調到事件循環中,然後當I/O操作完成時繼續執行。回調描述了該如何處理某個事件。事件循環輪詢所有的事件,當事件到來時將它們分配給等待處理事件的回調函數。這種方式讓程序儘可能的得以執行而不需要用到額外的線程。事件驅動型程序比多線程程序更容易推斷出行為,因為程序員不需要關心線程安全問題。

當我們面對如下的環境時,事件驅動模型通常是一個好的選擇:

程序中有許多任務,而且…
任務之間高度獨立(因此它們不需要互相通信,或者等待彼此)而且…
在等待事件到來時,某些任務會阻塞。


當應用程序需要在任務間共享可變的數據時,這也是一個不錯的選擇,因為這裡不需要採用同步處理。

網絡應用程序通常都有上述這些特點,這使得它們能夠很好的契合事件驅動編程模型。

3、 事件驅動的實現

實現:通常使用select、poll、epoll這類io複用+非阻塞來實現;事件驅動庫也大都是對前面的封裝。

缺點:業務不連續,尤其完成某個事情需要多個事件驅動操作時,代碼的可理解性不好。

改進:

1) 使用協程庫:可以把回調函數轉換成同步操作 ;

從效率上來說事件驅動應該是最高的了。

2) 程序架構的合理設計,超出兩個異步調用就要進行額外的功能封裝

4、 常用的事件驅動有哪些

Libevent

Libev

Libuv

Libubox


分享到:


相關文章: