Java NIO學習與記錄(六): NIO線程模型


 上一篇說的是基於操作系統的IO處理模型,那么這一篇來介紹下服務器端基於IO模型和自身線程的處理方式。

一、基於BIO下的線程處理模式

這種處理模型是基於阻塞IO進行的,上一篇講過,阻塞IO會阻塞每一個IO操作,直到事件就緒,下面來看下阻塞IO下的服務端線程模型:

圖1

如上圖所示,該線程模型基於阻塞IO模型實現,針對每個請求都需要抽出來一個線程進行處理讀入數據、業務處理數據、返回響應結果給客戶端,這個過程中讀、寫操作均會阻塞,且跟業務處理串行執行,該模式下,並發量過大時會大量創建線程,發生的大量上下文切換,從而導致CPU資源占用過大,當連接建立后,若當前線程暫無可讀數據,則線程會一直阻塞在讀操作上,造成線程資源浪費,即便使用線程池進行優化,雖然避免了大量創建線程,但也會出現線程資源浪費的問題,高並發下可能會造成排隊、響應不及時的問題。

具體BIO服務器的實現參考:SocketChannel與BIO服務器

二、基於NIO下的Reactor線程模型

利用操作系統NIO的API實現,Java對其API的調用進行了封裝(select等),這里先不探討怎么利用java的api去調用,先來看看它的基本流程是怎樣的,Reactor模式下的縣線程模型又會根據線程數量、線程池數量的不同,細分了三種線程模型。 

2.1:單Reactor單線程模型

這是最簡單的Reactor模型,整個過程中的事件處理全部發生在一個線程里:

圖2

上圖示意就是個簡單的NIO單Reactor單線程處理模型,流程如下:

①Reactor對象通過select監聽客戶端的請求事件,收到事件消息后通過dispatch進行任務分發。

②如果是建連請求,則交由Acceptor對象處理連接請求,然后創建一個Handler對象繼續完成后續處理

③若不是建連請求,則dispatch會調用對應連接的Handler進行處理,Handle負責完成連接成功后的后續處理(讀操作、寫操作、業務處理等)

此模型很簡單,易於理解,但是存在一定的問題,比如單線處理程模型下,無法發揮多核CPU的性能,如果Handler上的業務處理很慢,則意味着整個程序無法處理其他連接事件,造成性能問題。

適用於業務處理快速、客戶端連接較少的情況。

2.2:單Reactor多線程模型

相較於上面的模型,對業務處理模塊進行了異步處理,流程圖如下:

圖3

上圖示意屬於單Reactor多線程處理模型,流程如下:

①Reactor對象通過select監聽客戶端的請求事件,收到事件消息后通過dispatch進行任務分發。

②如果是建連請求,則交由Acceptor對象處理連接請求,然后創建一個Handler對象繼續完成后續處理

③若不是建連請求,則dispatch會調用對應連接的Handler進行處理,Handle負責完成連接成功后的讀操作,讀出來數據后的業務處理部分交由線程池異步處理,業務處理完成后發送給Handler處理完成的消息,然后再由Handler發送處理響應信息給對應的Client。

本模型充分利用了多核CPU的處理能力,降低了由業務處理引起的性能問題,Reactor線程僅負責接收連接、讀寫操作。但是Reactor除了負責連接處理外仍然負責讀寫操作,大量的請求下仍然可能仍然存在性能問題。 

2.3:主從Reactor多線程模型

這個模型中將會獨立出另一個Reactor對象來處理非連接處理的其他處理,命名為從Reactor(SubReactor),流程圖如下:

圖4

上圖示意屬於主從Reactor多線程處理模型,流程如下:

①主Reactor對象(MainReactor)通過select監聽客戶端的連接事件,收到連接事件后交由Acceptor處理。

②Acceptor處理完成后,MainReactor將此連接分配給SubReactor處理,SubReactor將此連接加入連接隊列進行事件監聽並建立Handler進行后續的各種操作,同上面的模型一致,SubReactor會監聽新的事件,如果有新的事件發生,則調用Handler進行相應的處理。

③Handler讀出來數據后的業務處理部分交由線程池異步處理,業務處理完成后發送給Handler處理完成的消息,然后再由Handler發送處理響應信息給對應的Client。

該模型存在兩個線程分別處理Reactor事件,主線程只負責處理連接事件,子線程只負責處理讀寫事件,這樣主線程可以處理更多的連接,而不用關心子線程里的讀寫處理是否會影響到自己。目前這種模型被廣泛使用在各種項目中(如Netty、Memcached等)。

 

以上的線程模型都是基於同步IO,異步IO這里不作說明,目前大部分項目都采用NIO的API進行實現(該模式下又分成了上述3種線程處理模型)。

下一篇將會針對NIO下的三種線程處理模型,介紹下Selector,以及利用Selector來寫一下具體的實現代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM