1. 程式人生 > >Java NIO/BIO 淺談 同步/非同步與阻塞/非阻塞

Java NIO/BIO 淺談 同步/非同步與阻塞/非阻塞

在我們瞭解Java NIO/BIO的網路通訊之前,我們先了解一下常用的阻塞/非阻塞模型以及同步/非同步的概念

一、阻塞和非阻塞

從簡單的開始,我們以經典的讀取檔案的模型舉例。(對作業系統而言,所有的輸入輸出裝置都被抽象成檔案。)在發起讀取檔案的請求時,應用層會呼叫系統核心的I/O介面。

如果應用層呼叫的是阻塞型I/O,那麼在呼叫之後,應用層即刻被掛起,一直出於等待資料返回的狀態,直到系統核心從磁碟讀取完資料並返回給應用層,應用層才用獲得的資料進行接下來的其他操作。

如果應用層呼叫的是非阻塞I/O,那麼呼叫後,系統核心會立即返回(雖然還沒有檔案內容的資料),應用層並不會被掛起,它可以做其他任意它想做的操作。(至於檔案內容資料如何返回給應用層,這已經超出了阻塞和非阻塞的辨別範疇。)

這便是(脫離同步和非同步來說之後)阻塞和非阻塞的區別。總結來說,是否是阻塞還是非阻塞,關注的是介面呼叫(發出請求)後等待資料返回時的狀態。被掛起無法執行其他操作的則是阻塞型的,可以被立即「抽離」去完成其他「任務」的則是非阻塞型的。

二、同步和非同步

阻塞和非阻塞解決了應用層等待資料返回時的狀態問題,那系統核心獲取到的資料到底如何返回給應用層呢?這裡不同型別的操作便體現的是同步和非同步的區別。

對於同步型的呼叫,應用層需要自己去向系統核心問詢,如果資料還未讀取完畢,那此時讀取檔案的任務還未完成,應用層根據其阻塞和非阻塞的劃分,或掛起或去做其他事情(所以同步和非同步並不決定其等待資料返回時的狀態);如果資料已經讀取完畢,那此時系統核心將資料返回給應用層,應用層即可以用取得的資料做其他相關的事情。

而對於非同步型的呼叫,應用層無需主動向系統核心問詢,在系統核心讀取完檔案資料之後,會主動通知應用層資料已經讀取完畢,此時應用層即可以接收系統核心返回過來的資料,再做其他事情。

這便是(脫離阻塞和非阻塞來說之後)同步和非同步的區別。也就是說,是否是同步還是非同步,關注的是任務完成時訊息通知的方式。由呼叫方盲目主動問詢的方式是同步呼叫,由被呼叫方主動通知呼叫方任務已完成的方式是非同步呼叫。

三、Java 網路通訊

3.1 基本概念

在Java網路通訊中,最基本的概念就是Socket程式設計了。Socket又稱“套接字” 向網路發出請求或者應答網路請求。

Socket 和ServerSocket類庫位於Java.net 包中。ServerSocket用於伺服器端,Socket是建立網路連線時使用的。在連線成功時,應用程式兩端都會產生一個Scoket例項,操作這個例項,完成所需要的會話。對於一個網路連線來說,套接字是平等的,不因為在伺服器端或者在客戶端而產生不同的級別。不管是Socket還是ServerSocket他們的工作都是通過SocketImpl類及其子類完成的。

套接字之間的連線過程可以分為四個步驟:伺服器監聽,客戶端請求伺服器,伺服器確認,客戶端確認,進行通訊。

1)伺服器監聽:是伺服器套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態。

2)伺服器請求:是指由客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描敘它要連線的伺服器的套接字,指出伺服器的套接字的地址和埠,然後就像伺服器套接字提出連線請求。

3)伺服器連線確認:是指當伺服器套接字監聽到或者說接收到客戶端套接字的連線請求,它就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端的套接字的描述傳送給客戶端。

4)客戶端連線確認:一旦客戶端確認了此描敘,連線就建立完成了,雙方開始通訊。而伺服器套接字繼續處於監聽狀態;繼續接受其他網路套接字的連線請求。

3.2 阻塞和非阻塞

阻塞:應用程式在獲取網路資料的時候,如果程式傳輸資料很慢,那麼程式就一直等待著,直到資料傳輸完成。

非阻塞:應用程式直接可以獲取已經準備就緒的資料, 無須等待。

BIO和NIO的本質區別就是阻塞和非阻塞。

3.3 同步和非同步

同步和非同步一般是面向作業系統與應用程式對I/O操作的層面上區別的。

同步:應用程式會直接參與IO讀寫操作,並且我們的應用程式會直接阻塞到某個方法上,直到資料準備完畢。

非同步:所有的IO操作交個作業系統處理,與我們應用程式沒有直接關係,我們程式不需要關係IO讀寫,當作業系統完成了 IO讀寫的時候,會給我們應用程式發出通知,資料傳輸完畢。

3.4 在Java網路通訊中同步和非同步 阻塞和非阻塞

同步非同步說的是Server伺服器端的執行方式

阻塞和非阻塞說的就是接受資料的方式

BIO為同步阻塞模式,NIO為同步非阻塞。NIO並沒有實現非同步,在JDK1.7以後,升級了NIO庫包,指出非同步非阻塞通訊模式NIO 2.0(AIO)。