NIO,全称为“New IO”,是Java 1.4 引入的一套用于更高效的 I/O 操作的API。NIO主要包括以下三个核心组件:Channel、Buffer 和 Selector。其中,Channel 和 Buffer 主要用于底层数据传输,Selector 则用于监听 Channel 上的 IO 事件。
Java 基础之NIO 学习详解
简述
NIO,全称为“New IO”,是Java 1.4 引入的一套用于更高效的 I/O 操作的API。NIO主要包括以下三个核心组件:Channel、Buffer 和 Selector。其中,Channel 和 Buffer 主要用于底层数据传输,Selector 则用于监听 Channel 上的 IO 事件。
NIO 与传统 IO 的区别
在传统 IO 模型中,当一个线程被分配到一个 Socket 后,这个线程就会一直阻塞等待,直到数据到达,而在 NIO 模型中,数据异步地读取到缓冲区,线程可以继续处理其他请求,从而提高了系统的并发处理能力。
NIO 的核心组件
Channel
Channel 可以看作是一个数据源的抽象。例如文件、网络套接字或一个能够实现 I/O 操作的硬件设备都可以通过 Channel 进行数据读写。Channel 与 Stream 的区别就像是将数据源分成了读取与写入两个部分。
Buffer
Buffer 可以看作是一个存储字节的数组。它有一个指针 position 表示下一个读或写的位置,一个 limit 表示结束位置,一个 capacity 表示数组的容量。当Buffer缓冲区中有数据读写时,指针 position 会向前移动。
Selector
Selector 用于监听多个 Channel 上的 I/O 事件。因为在 NIO 中,一个线程可以监听多个 Channel,因此使用 Selector 可以节省线程开销,提高程序的并发性能。
NIO应用
下面我们来看一些 NIO 应用实例。
示例1:NIO读取文件
public static void readFile(String path) throws IOException {
RandomAccessFile file = new RandomAccessFile(path, "rw");
FileChannel channel = file.getChannel();
// 初始化 ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = channel.read(buffer);
while (bytesRead != -1) {
// 将 ByteBuffer 从写模式变成读模式
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
bytesRead = channel.read(buffer);
}
channel.close();
file.close();
}
示例2:NIO服务器
这是一个基于NIO的简单服务器应用,可以同时处理多个客户端请求。
public static void server() throws IOException {
// 创建 ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8888));
serverSocketChannel.configureBlocking(false);
// 创建 Selector
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyChannelsCount = selector.select();
if (readyChannelsCount == 0) {
continue;
}
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
// 新的客户端连接
SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println("New client connected");
} else if (key.isReadable()) {
// 读取客户端请求
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);
if (bytesRead > 0) {
buffer.flip();
String request = new String(buffer.array(), 0, bytesRead);
System.out.println("Received request: " + request);
// 处理请求
// 发送响应
buffer.clear();
String response = "Hello, client";
buffer.put(response.getBytes());
buffer.flip();
socketChannel.write(buffer);
} else {
socketChannel.close();
System.out.println("Client disconnected");
}
}
iterator.remove();
}
}
}
以上是关于 NIO 的一个简单介绍以及两个示例的详细说明。
本文标题为:Java 基础之NIO 学习详解


- Java中4种经典限流算法讲解 2023-03-30
- 用Java实现简单画板功能 2022-12-27
- Spring MVC自定义日期类型转换器实例详解 2023-07-31
- SpringBoot采用AJAX实现异步发布帖子详解 2022-09-03
- SpringBoot使用AOP实现统计全局接口访问次数详解 2023-01-13
- 详解Java如何利用数字描述更多的信息 2023-05-13
- 解析HikariCP一百行代码轻松掌握多线程 2023-06-02
- JDK8中String的intern()方法实例详细解读 2023-05-25
- java如何将一个float型数的整数部分和小数分别输出显示 2023-02-28
- Java线程池源码的深度解析 2023-06-23