Java NIO(New I/O)是一个提供非阻塞I/O操作的API,相较于传统的Java I/O,它可以更高效地处理多个并发连接
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
Selector
对象:Selector selector = Selector.open();
ServerSocketChannel
对象,并配置为非阻塞模式:ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress("localhost", 8080));
ServerSocketChannel
注册到Selector
上,并监听OP_ACCEPT
事件(客户端连接请求):serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 等待事件发生,此处会阻塞
selector.select();
// 获取已发生事件的SelectionKey集合
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
// 遍历事件集合
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// 处理客户端连接请求
if (key.isAcceptable()) {
SocketChannel clientSocketChannel = serverSocketChannel.accept();
clientSocketChannel.configureBlocking(false);
clientSocketChannel.register(selector, SelectionKey.OP_READ);
}
// 处理客户端数据读取
else if (key.isReadable()) {
SocketChannel clientSocketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = clientSocketChannel.read(buffer);
if (bytesRead == -1) {
// 客户端已关闭连接
clientSocketChannel.close();
} else {
buffer.flip();
System.out.println("Received: " + new String(buffer.array(), 0, bytesRead));
}
}
// 移除已处理的事件
keyIterator.remove();
}
}
serverSocketChannel.close();
selector.close();
这个示例展示了如何使用Java NIO实现一个简单的多线程echo服务器。当客户端连接时,服务器会注册一个OP_READ
事件,以便在客户端发送数据时读取数据。当客户端发送数据时,服务器会读取数据并将其打印到控制台。
这种方法的优势在于,服务器可以同时处理多个客户端连接,而无需为每个连接创建新的线程。这有助于提高系统资源的利用率和扩展性。然而,在处理大量并发连接时,可能需要调整操作系统的文件描述符限制和JVM的线程栈大小等参数。