Java中的IO方式主要分為3種:BIO(同步阻塞)、NIO(同步非阻塞)和AIO(非同步非阻塞)。 BIO
同步阻塞模式。在JDK1.4以前,使用Java建立網路連接時,只能採用BIO方式,在伺服器端啟動一個ServerSocket,然後使用accept等待用戶端請求,對於每一個請求,使用一個線程來進行處理使用者請求。線程的大部分時間都在等待請求的到來和IO操作,利用率很低。而且線程的開銷比較大,數量有限,因此伺服器同時能處理的串連數也很低。 NIO
BIO模式中,是“一個Socket一個線程”;而在NIO中則是使用單個或少量的線程來輪詢Socket,當發現Socket上有請求時,才為請求分配線程。因此是“一個請求一個線程”。
具體實現就是把Socket通過Channel註冊到Selector,使用一個線程在Selector中輪詢,發現Channel有讀寫的事件,就可以分配給其他線程來處理(通常使用線程池)。 AIO
從JDK7開始支援AIO模式。通過AsynchronousServerSocketChannel中註冊事件回呼函數來處理商務邏輯。當IO操作完成以後,回呼函數會被調用。如果傳入AsynchronousChannelGroup,可以綁定線程池來處理事件。
關於JDK的實現,Windows平台基於IOCP實現AIO,Linux只有eppoll類比實現了AIO。
附:關於IO經常提到Reactor/ Proactor模式。
這兩個模式中都有兩個角色:事件多路分離器(Event Demultiplexer)和事件處理器(Event Handler)。分離器負責對監聽IO事件,並通知處理器;處理器負責對IO內容進行處理,完成對應的業務。
二者的差異,以讀操作為例(寫操作類似)。
Reactor中實現讀:
1. 註冊讀就緒事件和相應的事件處理器。
2. 事件分離器等待事件。
3. 事件到來,啟用分離器,分離器調用對應的處理器。
4. 處理器完成IO讀操作,處理讀到的資料,註冊新的事件,然後返還控制權。
Proactor中實現讀:
1. 註冊讀完成事件和相應的事件處理器(包括緩衝區地址)。
2. 事件分離器等待操作完成事件的同時,作業系統利用並行的核心線程執行實際的讀操作,並將結果資料存入使用者自訂緩衝區,最後通知事件分離器讀操作完成。
3. 事件分離器呼喚處理器。
4. 事件處理器處理使用者自訂緩衝區中的資料,然後啟動一個新的非同步作業,並將控制權返回事件分離器。
由此可見,兩者的主要區別:Reactor中,由使用者線程(事件處理器所線上程)完成IO的讀寫操作;而在Proactor中,是由作業系統完成IO讀寫操作後,再通知事件處理器,使用者線程只完成對資料的商務邏輯處理部分。