BIO、NIO、AIO及網路程式設計
一. 網路程式設計的一些基礎
1.先說明一下執行緒的掛起、阻塞、睡眠
執行緒從建立、執行到結束總是處於下面五個狀態之一:新建狀態、就緒狀態、執行狀
態、阻塞狀態及死亡狀態。下圖是使用時間片輪轉法的作業系統程序的狀態和它們之
間的轉換。
掛起和睡眠是主動的,掛起恢復需要主動完成,睡眠恢復則是自動完成的,因為
睡眠有一個睡眠時間,睡眠時間到則恢復到就緒態。而阻塞是被動的,是在等待某種
事件或者資源的表現,一旦獲得所需資源或者事件資訊就自動回到就緒態。睡眠和掛
起是兩種行為,阻塞則是一種狀態。
掛起:一般是主動的,由系統或程式發出,甚至於輔存中去join()、wait()是掛起。
阻塞:一般是被動的,在搶佔資源中得不到資源,被動的掛起在記憶體,等待某種資
源或訊號量(即有了資源)將他喚醒。sleep()是屬於阻塞。
2.同步/非同步
同步和非同步關注的是訊息通訊機制。
(1)同步:就是指在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。
按照這個定義,其實絕大多數函式都是同步呼叫。
(2)非同步:概念和同步相對。 當一個非同步過程呼叫發出後,呼叫者不會立刻得到結
果。實際處理這個呼叫的部件是在呼叫發出後, 通過狀態、通知來通知
呼叫者,或通過回撥函式處理這個呼叫。
舉例:當到銀行後, .可以去ATM機前排隊等候 – (排隊等候)就是同步等待訊息 .可以去
大廳拿號,等到排到我的號時, 櫃檯的人會通知我輪到我去辦理業務. – (等待別
人通知)就是非同步等待訊息。
3.阻塞/非阻塞
阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態(無所謂同
步或者非同步,注意這裡的“呼叫結果”就是指“2”中標黑的“呼叫”的結果)
(1)阻塞:阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起(被掛起就是阻塞,
因為是被動的)。函式只有在得到結果之後才會返回。 有人也許會把阻
塞呼叫和同步呼叫等同起來,實際上他是不同的。 對於同步呼叫來說,
很多時候當前執行緒還是啟用的,只是從邏輯上當前函式沒有返回而已。
(2)非阻塞:非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前,該函式不
會阻塞當前執行緒,而會立刻返回。
舉例:繼續上面的那個例子,不論是排隊等待,還是使用號碼等待通知,如果在這個
等待的過程中,等待者除了等待訊息之外不能做其它的事情,那麼該機制就是
阻塞的,表現在程式中,也就是該程式一直阻塞在該函式呼叫處不能繼續往下
執行。相反,有的人喜歡在銀行辦理這些業務的時候一邊打打電話發發簡訊一
邊等待,這樣的狀態就是非阻塞的。
二. Java BIO、NIO、AIO
1.概念
(1)Java BIO : 同步並阻塞,伺服器實現模式為一個連線一個執行緒,即客戶端有連
接請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不
做任何事情會造成不必要的執行緒開銷,當然可以通過執行緒池機制改
善。
好理解的解釋:執行緒發起IO請求,不管核心是否準備好IO操作,從
發起請求起,執行緒一直阻塞,直到操作完成。
(2)Java NIO : 同步非阻塞,伺服器實現模式為一個請求一個執行緒,即客戶端傳送
的連線請求都會註冊到多路複用器上,多路複用器輪詢到連線有
I/O請求時才啟動一個執行緒進行處理。
好理解的解釋:執行緒發起IO請求,立即返回;核心在做好IO操作的
準備之後,通過呼叫註冊的回撥函式通知執行緒做IO
操作,執行緒開始阻塞,直到操作完成。
(3)Java AIO(NIO.2) : 非同步非阻塞,伺服器實現模式為一個有效請求一個執行緒,客
戶端的I/O請求都是由OS先完成了再通知伺服器應用去啟動
執行緒進行處理。
好理解的解釋:執行緒發起IO請求,立即返回;記憶體做好IO操
作的準備之後,做IO操作,直到操作完成或
者失敗,通過呼叫註冊的回撥函式通知執行緒
做IO操作完成或者失敗
二. BIO、NIO、AIO的使用場景
(1)BIO方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比
較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程式直觀簡單易理解。
(2)NIO方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,
併發侷限於應用中,程式設計比較複雜,JDK1.4開始支援。
(3)AIO方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,
充分呼叫OS參與併發操作,程式設計比較複雜,JDK7開始支援。