概述
- 在使用JAVA NIO和多線程來進(jìn)行高并發(fā)Java服務(wù)端應(yīng)用程序設(shè)計(jì)時(shí),通常是基于Reactor線程模型來設(shè)計(jì)的。Reactor,即包含一個(gè)Java NIO的多路復(fù)用選擇器Selector的反應(yīng)堆,當(dāng)有反應(yīng)時(shí),即該Selector所管理的某個(gè)客戶端連接有IO事件過來時(shí),則在當(dāng)前線程或者分配到其他線程來處理該IO事件。
- Reactor線程模型通常由接收客戶端連接請求的acceptor線程和處理客戶端的IO請求的IO線程兩部分組成,而acceptor線程和IO處理線程可以是同一個(gè)線程,也可以是不同的線程或者是各自對應(yīng)一個(gè)線程池。
單線程Reactor模型
- 單線程Reactor模型是指由一個(gè)線程綁定一個(gè)Java NIO的多路復(fù)用選擇器Selector,由該線程來處理該Selector的所有IO事件,包括新客戶端連接建立請求,即監(jiān)聽套接字的IO事件,和已經(jīng)建立連接的客戶端套接字的所有IO事件請求,如數(shù)據(jù)讀寫。在單線程Reactor模型中,Reactor模型中的新客戶端連接建立的acceptor線程和已經(jīng)建立連接的客戶端套接字的IO請求處理的IO線程是同一個(gè)線程。
- 具體工作模式如圖:服務(wù)端使用一個(gè)線程來處理新客戶端的連接請求和已建立連接的客戶端的讀寫IO事件。

- 由于該Selector所管理的所有客戶端連接和服務(wù)端的監(jiān)聽套接字的IO請求都是由該線程來處理,所以如果當(dāng)前線程正在處理某個(gè)客戶端的數(shù)據(jù)讀寫IO請求,則無法處理當(dāng)前的新建立連接的客戶端請求,導(dǎo)致客戶端無法建立連接或者連接超時(shí)。同時(shí)由于只使用一個(gè)線程所有也沒有充分利用多核CPU。
- 所以雖然通過使用單線程,規(guī)避了線程競爭和線程上下文切換,但是由于單個(gè)線程處理能力有限,所以單線程Reactor模型也無法支撐高并發(fā)客戶端請求的場景,Java服務(wù)端應(yīng)用程序設(shè)計(jì)很少使用到該模型。
單Acceptor線程多IO線程的Reactor模型
- 多線程Reactor模型與單線程Reactor模型的主要區(qū)別是已經(jīng)建立連接的客戶端套接字的IO事件是在另外一個(gè)線程或者另外一個(gè)線程池來處理的,這種線程也稱為IO線程,而處理監(jiān)聽套接字的新客戶端連接請求的線程則還是一個(gè)獨(dú)立的Acceptor線程。
- 具體工作過程如圖所示:使用在一個(gè)獨(dú)立Acceptor線程通過監(jiān)聽套接字監(jiān)聽客戶端的連接請求,當(dāng)有新的客戶端連接到來時(shí),創(chuàng)建該客戶端對應(yīng)的channel并注冊到其他一個(gè)IO線程的Selector,由該Selector監(jiān)視和獲取該客戶端channel后續(xù)的讀寫IO事件并進(jìn)行處理。

- 以上示意圖是針對一個(gè)已建立連接的客戶端套接字的所有IO請求可以是始終在IO線程池中的一個(gè)IO線程中處理。不過也可以是使用一個(gè)專門的IO線程來負(fù)責(zé)監(jiān)視所有客戶端的channels,當(dāng)某個(gè)客戶端有IO事件到來時(shí),將該客戶端的此次IO事件封裝為一個(gè)Runnable的任務(wù),交給另外的線程池處理,即某個(gè)客戶端的所有IO事件會(huì)在不同中線程處理。不過推薦是始終在一個(gè)IO線程中處理,這樣就不存在多個(gè)線程對該客戶端套接字進(jìn)行并發(fā)操作的場景,即不需要通過加鎖之類的操作來對該客戶端套接字對應(yīng)的channel對象引用進(jìn)行線程同步。
- 這種已建立連接的客戶端的所有IO事件都是在同一個(gè)IO線程中處理的方式也是netty4的IO線程模型,通過客戶端channel與線程的綁定來避免線程競爭來提高性能。
多Acceptor線程多IO線程Reactor模型
- 多Acceptor線程多IO線程Reactor模型實(shí)際與單Acceptor線程多IO線程Reactor模型差不多,主要一個(gè)區(qū)別就是用于接收客戶端的連接請求的線程不再是只使用一個(gè)acceptor線程,而是使用一個(gè)包含多個(gè)acceptor線程的線程池,從而解決單個(gè)acceptor線程在處理多個(gè)不同的端口的高并發(fā)客戶端連接建立請求時(shí)的性能瓶頸,即當(dāng)服務(wù)端需要同時(shí)監(jiān)聽多個(gè)端口時(shí),可以使用一個(gè)包含多個(gè)Acceptor線程的線程池。
- 該模型的工作過程如圖所示:使用多個(gè)Acceptor線程來處理客戶端的連接請求。
