一文彻底熟练掌握并使用Java的NIO操作
一、基本概念
Java NIO 是 Java 1.4 引入的,用于处理高速、高并发的 I/O 操作。与传统的阻塞 I/O 不同,NIO 支持非阻塞 I/O 和选择器,可以更高效地管理多个通道。
二、核心组件
- 通道(Channel)
Channel是 NIO 中用于读取和写入数据的主要接口,提供双向数据传输的能力。- 常见的通道实现:
FileChannel:用于文件的读写操作。SocketChannel:用于 TCP 网络通信。ServerSocketChannel:用于监听 TCP 连接的服务器端通道。DatagramChannel:用于 UDP 网络通信。
- 缓冲区(Buffer)
Buffer是 NIO 中用于存储数据的容器。与传统的流不同,NIO 通过缓冲区进行数据的读写。- 常见的缓冲区类型:
ByteBuffer:处理字节数据。CharBuffer:处理字符数据。IntBuffer、LongBuffer等:处理整型和长整型数据。
- 缓冲区有三个重要的属性:
position:当前缓冲区的读写位置。limit:可以读取或写入的最大数据量。capacity:缓冲区的总容量。
- 选择器(Selector)
Selector是 NIO 的核心组件之一,允许单个线程监控多个通道的事件。- 通过选择器,可以处理多个连接而不需要为每个连接都创建一个线程。
- Selector 的工作流程:
- 注册通道(Channel)到选择器。
- 选择感兴趣的通道(如可读、可写、连接等)。
- 处理就绪的通道。
三、底层实现
文件描述符
NIO 底层仍然依赖操作系统的文件描述符。每个通道对应一个文件描述符,用于直接与操作系统进行交互。
事件驱动
NIO 使用事件驱动的机制。选择器会调用操作系统的底层 API(如 epoll、kqueue)来获取就绪事件。这种机制允许线程在等待事件时处于睡眠状态,从而减少 CPU 资源的消耗。
四、设计原理
非阻塞 IO
NIO 允许通道在没有可用数据时不阻塞线程。线程可以继续执行其他操作,适合处理高并发请求。
选择性处理
使用选择器,可以选择性地处理就绪通道,避免了为每个连接创建一个线程的开销。
适应性强
NIO 的设计使得它可以处理各种数据源(如文件、网络等),提高了灵活性。
五、底层原理
内存管理
NIO 的缓冲区(Buffer)底层使用
java.nio.HeapByteBuffer和java.nio.DirectByteBuffer,后者直接在 JVM 之外分配内存,减少了与 JVM 堆内存的交互开销,提升了 I/O 性能,特别是在大数据量传输时。内存映射文件(Memory-Mapped File)
NIO 的
FileChannel支持内存映射文件,允许将文件映射到内存。这种方式使得文件内容可以像数组一样直接操作,大幅提升了文件读取和写入的速度,特别适用于大文件处理和高性能数据库实现。选择器的实现
选择器的实现通常基于操作系统提供的高效 I/O 多路复用机制,如 Linux 的
epoll或 Windows 的IOCP。这些机制使得 NIO 能够在处理大量并发连接时表现优异。了解这些底层实现的机制,能够帮助开发者在不同操作系统上优化性能。
六、使用场景
高性能 Web 服务器
NIO 适合构建高性能的 Web 服务器,如 Netty 框架,利用其事件驱动和异步非阻塞的特性,可以处理数万并发连接,而不需要为每个连接创建一个线程。
实时数据处理
在需要实时处理大量数据的应用(如金融交易系统、在线游戏等),NIO 提供的低延迟和高吞吐量使其成为理想选择。
跨平台的网络通信
NIO 的通道和选择器机制提供了跨平台的网络通信能力,开发者可以轻松构建支持多种操作系统的网络应用。
高并发网络应用
NIO 适用于需要处理大量并发连接的应用,例如聊天服务器、HTTP 服务器和在线游戏等。
异步文件处理
使用
AsynchronousFileChannel进行异步文件读写操作,适合需要高性能的文件处理场景。
七、性能特点
降低上下文切换
NIO 的非阻塞特性降低了线程切换的开销,特别是在高并发情况下,提高了应用的吞吐量。
内存映射文件
NIO 支持内存映射文件,可以将文件直接映射到内存,这种方式可以提高对大文件的访问速度。
减少资源占用
由于使用选择器管理多个通道,NIO 可以减少对系统资源(如线程和内存)的占用,提高整体性能。
八、示例代码
以下是一个简单的 NIO 服务器示例,使用选择器处理客户端连接:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.SelectionKey;
public class NioServer {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // 阻塞,直到有事件发生
for (SelectionKey key : selector.selectedKeys()) {
if (key.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(256);
int bytesRead = socketChannel.read(buffer);
if (bytesRead == -1) {
socketChannel.close();
} else {
buffer.flip();
// 处理数据...
socketChannel.write(buffer);
}
}
}
selector.selectedKeys().clear(); // 清除已处理的事件
}
}
}
一文彻底熟练掌握并使用Java的NIO操作的更多相关文章
- 使用DOM进行xml文档的crud(增删改查)操作<操作详解>
很多朋友对DOM有感冒,这里我花了一些时间写了一个小小的教程,这个能看懂,会操作了,我相信基于DOM的其它API(如JDOM,DOM4J等)一般不会有什么问题. 后附java代码,也可以下载(可点击这 ...
- java之NIO编程
所谓行文如编程,随笔好比java文件,文章好比类,参考文献是import,那么目录就是方法定义. 本篇文章处在分析thrift的nonblocking server之前,因为后者要依赖该篇文章的知识. ...
- JAVA 探究NIO
事情的开始 1.4版本开始,java提供了另一套IO系统,称为NIO,(New I/O的意思),NIO支持面向缓冲区的.基于通道的IO操作. 1.7版本的时候,java对NIO系统进行了极大的扩展,增 ...
- java字符流操作flush()方法及其注意事项
java字符流操作flush()方法及其注意事项 flush()方法介绍 查阅文档可以发现,IO流中每一个类都实现了Closeable接口,它们进行资源操作之后都需要执行close()方法将流关闭 ...
- java 的nio与io对比
转:本文并非Java.io或Java.nio的使用手册,也不是如何使用Java.io与Java.nio的技术文档.这里只是尝试比较这两个包,用最简单的方式突出它们的区别和各自的特性.Java.nio提 ...
- java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解
java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解 我用的是office word 2016版 XWPFRun是XWPFDocument中的一段文本对象(就是一段文 ...
- Tinking in Java ---Java的NIO和对象序列化
前面一篇博客的IO被称为经典IO,因为他们大多数都是从Java1.0开始就有了的:然后今天这篇博客是关于NIO的,所以的NIO其实就是JDK从1.4开始,Java提供的一系列改进的输入/输出处理的新功 ...
- 少啰嗦!一分钟带你读懂Java的NIO和经典IO的区别
1.引言 很多初涉网络编程的程序员,在研究Java NIO(即异步IO)和经典IO(也就是常说的阻塞式IO)的API时,很快就会发现一个问题:我什么时候应该使用经典IO,什么时候应该使用NIO? 在本 ...
- Java BIO NIO 与 AIO
回顾 上一章我们介绍了操作系统层面的 IO 模型. 阻塞 IO 模型. 非阻塞 IO 模型. IO 复用模型. 信号驱动 IO 模型(用的不多,知道个概念就行). 异步 IO 模型. 并且介绍了 IO ...
- Java 正则表达式实例操作
Regular Expression正则表达式,简称RegExp,常规通用的表达式,在多个开发语言中都有它的实现,可以通过正则表达式来快速的检索.匹配.查找.替换字符串中的文本. 简单实例 匹配网址 ...
随机推荐
- Mysql 不用Json存储 List<Long>的方式
public static void main(String[] args) { List<Long> idList = new ArrayList<>(); for (int ...
- Linux驱动小技巧 | 利用DRIVER_ATTR实现调用内核函数
1. 前言 很多朋友在调试驱动的时候,都会遇到这样一个场景: 修改一个参数,然后调用某个内核中的函数. 比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等. 如果每一个参数都通过字符设备的ioc ...
- k8s获取集群内所有在使用镜像
kubectl get pods --all-namespaces -o jsonpath="{..image}" | tr -s '[[:space:]]' ' ' | sort ...
- Terraform管理云资源实践
背景 Terraform是一款开源的Cli工具,网上的很多文章都是单机安装一个然后创建个目录就去操作云资源:如果在高可用的前提,如何将Terraform cli变成一个嵌入运维流程的一个组件?不仅仅是 ...
- Kubernetes-13:存储卷Volume介绍及使用
Volume介绍 Volume存在的意义 容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题,首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将丢失--容器以 ...
- 即构 UIKits 重磅发布!高效开发与自定义UI兼备,打造互动场景新标杆
即构UIKits上线,新一代场景化实时互动SDK! 即构科技发布了首款面向中小团队的整合型实时互动产品UIKits , 基于场景化最佳实践,整合RTC.IM.直播.美颜等多款产品,打造了音视频通话UI ...
- InfoTS: 具有信息感知增强的时间序列对比学习《Time Series Contrastive Learning with Information-Aware Augmentations》(对比学习、信息感知增强、高保真、多样性、信息论-信息瓶颈、元学习器)(没看懂,还需要再回顾)
现在是2024年5月23日,14:30,开始看论文. 论文:Time Series Contrastive Learning with Information-Aware Augmentations ...
- Qml 实现水波进度动画条
[写在前面] 最近看到一个非常有趣的动画效果:水波进度动画. 学习了一下实现思路,觉得很有意思. 不过原版是 HTML + CSS,我这里用的是 Qml,有一些小技巧,分享给大家~ [正文开始] 老样 ...
- CSS & JS Effect – Blue Tick Avatar
效果 难点 难题只有一个, 那就是如何把 blue tick image 定位当 avatar 的右下角. HTML <div class="avatar-wrapper"& ...
- Identity – Without Identity Framework
前言 上一回研究 Authenticate 和 Authorization 已经是 2 年前了. 业务需求一直没有增长, 所以也没有再去提升它了. 但最近业务开始上去了. 荒废的功夫又得拾起来了. 上 ...