Java NIO(Non-blocking I/O)提供了一种非阻塞I/O的实现方式,使得一个线程可以管理多个通道。相比于传统的I/O,非阻塞I/O可以更好地处理高并发的情况,提高系统的吞吐量。
非阻塞I/O的实现方式是将通道设置为非阻塞模式,这样当通道没有准备好读或写时,不会一直阻塞等待,而是立即返回。这样线程就可以继续执行其他操作,等通道准备好后再进行读写操作。在非阻塞模式下,读写操作需要在一个循环中不断进行,直到完成所有操作。
Java NIO中,通道必须在非阻塞模式下才能使用选择器(Selector)。选择器可以用来监听多个通道的事件,比如读就绪、写就绪等,从而避免了阻塞模式下每个通道都需要一个线程进行监听的问题。使用选择器可以大大提高系统的并发处理能力。
下面是一个简单的Java NIO非阻塞模式的示例代码:
public class NonBlockingServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress("localhost", 8080));
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);
if (bytesRead == -1) {
socketChannel.close();
continue;
}
buffer.flip();
String message = new String(buffer.array(), 0, bytesRead);
System.out.println("Received message: " + message);
}
}
}
}
}
这段代码实现了一个简单的非阻塞模式的服务器,可以接收客户端的连接请求,并读取客户端发送的数据。在代码中,我们首先将服务器通道设置为非阻塞模式,并注册到选择器上,监听OP_ACCEPT事件。然后使用循环来等待事件发生,当有事件发生时,我们遍历选择器的事件集合,根据事件类型进行不同的操作。如果是OP_ACCEPT事件,则接受客户端的连接请求,并将客户端通道注册到选择器上,监听OP_READ事件。如果是OP_READ事件,则读取客户端发送的数据。
在非阻塞模式下,通道和选择器的使用可以更加灵活和高效。