事件驅動引擎會取代多線程編程嗎

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

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

圖21.1 線程模型

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

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

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

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

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

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

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

下面客觀的談一下兩個經典引擎的區別:

多線程編程的特點

多線程通用用於併發編程,具有多個獨立的執行過程。共享線程間的狀態,具有一些同步的特點,例如Lock和Condition。調度方式是搶佔式。所有用戶進程共用一個內核線程。一個CPU最小的出現單元是一個線程而不是進程。

多線程編程的優勢

1.在多CPU的環境下面,可以體現出多核的性能。

多線程編程的劣勢

1.使用多線程編程是比較困難的,相對與事件編程來說,多線程編程是一件痛苦的事情。難以架構高性能的多線程程序。

2.標準庫的API一般都不是線程安全的。內核調用,Windows系統不是多線程的。

3.在使用鎖的時候,如果不謹慎,容易造成死鎖。

4.多線程編程難以調適,原因在於線程之間共享數據和時間片。很少的多線程編程調試工具。

事件驅動編程的特點

事件驅動編程通常只是用一個執行過程,CPU之間不是併發的,在處理多任務的時候,事件驅動編程是使用協作式處理任務,而不是多線程的搶佔式。事件驅動簡潔易用,只需要註冊感興趣的事件,在回調中設計邏輯,就可以了。在調用的過程中,事件循環在等待事件的發生,跟着調用Handler,事件Handler不是搶佔式的,Handler一般只有很短的生命週期。

事件驅動編程的優勢

1.在大部分的應用場景中,事件編程優與多線程編程。

2.相對與多線程編程來講,事件驅動編程比較容易,複雜度低,是開發者樂於接受的。

3.大多數的GUI框架,都是使用事件驅動編程了架構的。每一個事件會綁定一個Handler,這些事件通常是點擊按鈕,選擇菜單,等等。Handler來實現具體的行爲邏輯。

4.事件驅動經常使用在IO框架中,可以很好的實現IO複用。很多高性能的IO框架都是使用事件驅動模型的,例如:Netty,Mina。

5.易於調試。時間依賴只和事件有關係,而不是內部調度。問題容易暴露。

事件驅動編程的劣勢

1.如果Handler佔用時間較長,那會阻塞應用程序的響應。

2.無法通過時間來維護本地狀態,因爲Handler必須返回。

3.通常在單CPU環境下,比多線程編程要快,因爲沒有鎖的因素,沒有線程切換的損耗。CPU不是併發的,這樣的話就不適合用在一些科學計算的應用中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章