Java NIO(New IO)是Java 1.4引入的一组用于替代Java IO的API,其最大的特点就是支持非阻塞IO。Java NIO的非阻塞IO是基于选择器(Selector)和通道(Channel)实现的,与传统的Java IO API不同,它可以同时处理多个连接,而且这些连接不会阻塞线程。在Java NIO中,一个线程可以处理多个通道(连接),因此可以实现高并发。
Java NIO的网络编程模型有以下几个组成部分:
1、Channel:通道是Java NIO中一个基础的概念,它相当于Java IO中的Stream,但是它可以同时进行读写操作,而且可以进行非阻塞读写操作。
2、Buffer:缓冲区是一个容器,用来存储数据。Java NIO中所有数据都是用Buffer来处理的,Buffer实现了Java NIO中的非阻塞IO。
3、Selector:选择器是Java NIO中的另一个重要概念,它可以监视多个通道的IO状况,当某个通道的数据准备好了读写时,它就可以通知程序来进行处理。
Java NIO的网络编程模型基于事件驱动,当一个通道中有数据可读写时,Selector会通知程序进行处理。在处理数据时,程序需要从通道中读取数据到Buffer中,然后再从Buffer中处理数据。
下面是一个简单的Java NIO网络编程模型的示例代码,其中包含了Channel、Buffer和Selector的使用:
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.SocketChannel;
import java.util.Iterator;
public class NioClient {
public static void main(String[] args) {
try {
// 创建SocketChannel并连接到远程服务器
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost", 8888));
// 创建Selector并将SocketChannel注册到Selector上
Selector selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT);
while (true) {
// 阻塞等待就绪的事件,每隔1秒钟唤醒一次
if (selector.select(1000) == 0) {
continue;
}
// 处理就绪的事件
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isConnectable()) {
// 连接就绪,完成连接操作
SocketChannel channel = (SocketChannel) key.channel();
if (channel.isConnectionPending()) {
channel.finishConnect();
}
channel.configureBlocking(false);
channel.write(ByteBuffer.wrap("Hello, server".getBytes()));
channel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
// 可读就绪,读取数据并处理
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len = channel.read(buffer);
if (len > 0) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
System.out.println("Received from server: " + new String(bytes));
} else if (len < 0) {
channel.close();
key.cancel();
}
}
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
该示例代码实现了一个NIO客户端,其中:
1、创建一个SocketChannel并连接到远程服务器;
2、创建一个Selector并将SocketChannel注册到Selector上;
3、在循环中阻塞等待就绪的事件,每隔1秒钟唤醒一次;
4、处理就绪的事件:
1)如果是连接就绪事件,完成连接操作并将SocketChannel注册到Selector上,以便后续处理可读就绪事件;
2)如果是可读就绪事件,读取数据并处理。