NIO 教程
1. 概述
1.1 什么是 NIO?
NIO(New I/O)是 Java 1.4 引入的一组新的 I/O API,旨在提高 I/O 操作的效率和性能。NIO 提供了非阻塞 I/O 操作、缓冲区管理和通道等新特性,使得处理大量数据和高并发场景变得更加高效。
1.2 NIO 的核心组件
- Buffer(缓冲区):用于存储数据。
- Channel(通道):用于读写数据。
- Selector(选择器):用于管理多个通道的非阻塞 I/O 操作。
2. Buffer(缓冲区)
2.1 缓冲区的基本概念
缓冲区是 NIO 中用于存储数据的容器。每个缓冲区都有以下几个重要的属性:
- Capacity(容量):缓冲区可以存储的最大数据量。
- Position(位置):当前读写的位置。
- Limit(限制):当前缓冲区的有效数据量。
2.2 缓冲区的创建和使用
import java.nio.ByteBuffer;
public class BufferExample {
public static void main(String[] args) {
// 创建一个容量为10的ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(10);
// 写入数据
buffer.put((byte) 10);
buffer.put((byte) 20);
// 切换到读模式
buffer.flip();
// 读取数据
while (buffer.hasRemaining()) {
System.out.println(buffer.get());
}
// 清空缓冲区
buffer.clear();
}
}
3. Channel(通道)
3.1 通道的基本概念
通道是 NIO 中用于读写数据的管道。通道可以分为两类:
- FileChannel:用于文件 I/O。
- SocketChannel 和 ServerSocketChannel:用于网络 I/O。
3.2 文件通道的使用
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
public class FileChannelExample {
public static void main(String[] args) throws Exception {
FileInputStream input = new FileInputStream("input.txt");
FileOutputStream output = new FileOutputStream("output.txt");
FileChannel inputChannel = input.getChannel();
FileChannel outputChannel = output.getChannel();
// 从输入通道读取数据并写入输出通道
inputChannel.transferTo(0, inputChannel.size(), outputChannel);
input.close();
output.close();
}
}
4. Selector(选择器)
4.1 选择器的基本概念
选择器用于管理多个通道的非阻塞 I/O 操作。通过选择器,可以同时监听多个通道的事件,如连接、读取和写入。
4.2 选择器的使用
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;
public class SelectorExample {
public static void main(String[] args) throws Exception {
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (key.isAcceptable()) {
SocketChannel clientChannel = serverChannel.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
clientChannel.read(buffer);
buffer.flip();
System.out.println("Received: " + new String(buffer.array()));
}
}
}
}
}
5. 实践练习
5.1 练习1:文件复制
编写一个程序,使用 FileChannel 实现文件的复制功能。
5.2 练习2:简单的聊天服务器
编写一个简单的聊天服务器,使用 Selector 和 SocketChannel 实现多客户端的连接和消息传递。
6. 总结
NIO 提供了高效的 I/O 操作方式,特别适用于高并发和大数据量的场景。通过学习 Buffer、Channel 和 Selector,你可以更好地理解和应用 NIO 技术,提升程序的性能和效率。
7. 参考资料
通过本教程的学习,你应该能够掌握 NIO 的基本概念和使用方法,并能够在实际项目中应用这些知识。