簡介
從 Java 1.4 版本開始引入的一個新的 I/O API,可以替代標準的 Java I/O。 提供了與標準 I/O 不同的工作方式,核心是 通道(Channel)、緩沖區(Buffer) 和 選擇器(Selector)。 支持非阻塞 I/O 操作,非常適合處理大量并發連接,是構建高性能網絡應用的基礎。 多路復用的機制,適合構建高性能服務器應用
核心概念
Channel:類似于流(Stream),但可以雙向讀寫 Buffer:一個用于存儲數據的容器(本質上是一個數組) Selector:用于監聽多個 Channel 的事件(如連接、讀就緒、寫就緒)
一個線程可以管理多個 Channel,實現單線程處理多路復用,極大地提高了 I/O 效率
代碼示例
public class NIOClient { public static void main ( String [ ] args) throws IOException { SocketChannel socketChannel = SocketChannel . open ( ) ; socketChannel. connect ( new InetSocketAddress ( "localhost" , 8080 ) ) ; socketChannel. configureBlocking ( false ) ; System . out. println ( "已連接到服務器 localhost:8080" ) ; System . out. println ( "請輸入消息(輸入 'quit' 退出):" ) ; BufferedReader reader = new BufferedReader ( new InputStreamReader ( System . in) ) ; String userInput; ByteBuffer buffer = ByteBuffer . allocate ( 1024 ) ; while ( ( userInput = reader. readLine ( ) ) != null ) { if ( "quit" . equalsIgnoreCase ( userInput) ) { break ; } byte [ ] messageBytes = userInput. getBytes ( ) ; ByteBuffer writeBuffer = ByteBuffer . wrap ( messageBytes) ; socketChannel. write ( writeBuffer) ; System . out. println ( "已發送: " + userInput) ; buffer. clear ( ) ; int bytesRead = socketChannel. read ( buffer) ; if ( bytesRead > 0 ) { buffer. flip ( ) ; byte [ ] responseBytes = new byte [ buffer. remaining ( ) ] ; buffer. get ( responseBytes) ; String response = new String ( responseBytes) ; System . out. println ( "服務器回復: " + response) ; } } socketChannel. close ( ) ; System . out. println ( "客戶端已關閉。" ) ; }
}
public class NIOServer { public static void main ( String [ ] args) throws IOException { Selector selector = Selector . open ( ) ; ServerSocketChannel serverChannel = ServerSocketChannel . open ( ) ; serverChannel. configureBlocking ( false ) ; serverChannel. bind ( new InetSocketAddress ( 8080 ) ) ; serverChannel. register ( selector, SelectionKey . OP_ACCEPT) ; System . out. println ( "NIO 服務器啟動,監聽端口 8080..." ) ; while ( true ) { int readyChannels = selector. select ( ) ; if ( readyChannels == 0 ) continue ; Set < SelectionKey > selectedKeys = selector. selectedKeys ( ) ; Iterator < SelectionKey > keyIterator = selectedKeys. iterator ( ) ; while ( keyIterator. hasNext ( ) ) { SelectionKey key = keyIterator. next ( ) ; if ( key. isAcceptable ( ) ) { ServerSocketChannel server = ( ServerSocketChannel ) key. channel ( ) ; SocketChannel clientChannel = server. accept ( ) ; clientChannel. configureBlocking ( false ) ; clientChannel. register ( selector, SelectionKey . OP_READ) ; System . out. println ( "新客戶端連接: " + clientChannel. getRemoteAddress ( ) ) ; } else if ( key. isReadable ( ) ) { SocketChannel clientChannel = ( SocketChannel ) key. channel ( ) ; ByteBuffer buffer = ByteBuffer . allocate ( 256 ) ; int bytesRead = clientChannel. read ( buffer) ; if ( bytesRead > 0 ) { buffer. flip ( ) ; byte [ ] data = new byte [ buffer. remaining ( ) ] ; buffer. get ( data) ; String message = new String ( data) ; System . out. println ( "收到消息: " + message) ; ByteBuffer responseBuffer = ByteBuffer . wrap ( ( "Echo: " + message) . getBytes ( ) ) ; clientChannel. write ( responseBuffer) ; } else if ( bytesRead == - 1 ) { System . out. println ( "客戶端斷開: " + clientChannel. getRemoteAddress ( ) ) ; clientChannel. close ( ) ; } } keyIterator. remove ( ) ; } } }