简介
从 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 ( ) ; } } }