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正则表达式校验密码规则 2023-06-06
- mybatis-plus 如何操作json字段 2024-03-03
- Java顺序查找算法详解 2023-03-31
- Project Reactor源码解析publishOn使用示例 2023-04-13
- 如何解决Webservice第一次访问特别慢的问题 2023-02-10
- 详解Java面向对象之多态的原理与实现 2022-11-20
- 初识通用数据库操作类——前端easyui-datagrid,form(php) 2023-12-15
- SpringBoot多环境配置教程详解 2023-01-29
- mybatis水平分表实现动态表名的项目实例 2023-03-22
- Java设计模式之策略模式 2023-06-17