Java NIO 核心知识.下

[NIO 零拷贝](#NIO 零拷贝)

零拷贝是提升 IO 操作性能的一个常用手段,像 ActiveMQ、Kafka 、RocketMQ、QMQ、Netty 等顶级开源项目都用到了零拷贝。

零拷贝是指计算机执行 IO 操作时,CPU 不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及 CPU 的拷贝时间。也就是说,零拷贝主要解决操作系统在处理 I/O 操作时频繁复制数据的问题。零拷贝的常见实现技术有: mmap+writesendfilesendfile + DMA gather copy

下图展示了各种零拷贝技术的对比图:

可以看出,无论是传统的 I/O 方式,还是引入了零拷贝之后,2 次 DMA(Direct Memory Access) 拷贝是都少不了的。因为两次 DMA 都是依赖硬件完成的。零拷贝主要是减少了 CPU 拷贝及上下文的切换。

Java 对零拷贝的支持:

  • MappedByteBuffer 是 NIO 基于内存映射(mmap)这种零拷⻉⽅式的提供的⼀种实现,底层实际是调用了 Linux 内核的 mmap 系统调用。它可以将一个文件或者文件的一部分映射到内存中,形成一个虚拟内存文件,这样就可以直接操作内存中的数据,而不需要通过系统调用来读写文件。
  • FileChanneltransferTo()/transferFrom()是 NIO 基于发送文件(sendfile)这种零拷贝方式的提供的一种实现,底层实际是调用了 Linux 内核的 sendfile系统调用。它可以直接将文件数据从磁盘发送到网络,而不需要经过用户空间的缓冲区。关于FileChannel的用法可以看看这篇文章:Java NIO 文件通道 FileChannel 用法

代码示例:

private void loadFileIntoMemory(File xmlFile) throws IOException {

FileInputStream fis = new FileInputStream(xmlFile);

// 创建 FileChannel 对象

FileChannel fc = fis.getChannel();

// FileChannel.map() 将文件映射到直接内存并返回 MappedByteBuffer 对象

MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());

xmlFileBuffer = new byte[(int)fc.size()];

mmb.get(xmlFileBuffer);

fis.close();

}

总结

这篇文章我们主要介绍了 NIO 的核心知识点,包括 NIO 的核心组件和零拷贝。

如果我们需要使用 NIO 构建网络程序的话,不建议直接使用原生 NIO,编程复杂且功能性太弱,推荐使用一些成熟的基于 NIO 的网络编程框架比如 Netty。Netty 在 NIO 的基础上进行了一些优化和扩展比如支持多种协议、支持 SSL/TLS 等等。

相关推荐
G丶AEOM35 分钟前
Redis与MySQL如何保证数据一致性
java·redis
北漂编程小王子1 小时前
maven <scope>compile</scope>作用
java·maven·compile标签作用
小手cool1 小时前
IDEA某个Impl下的引入的文件红色
java·intellij-idea
yours_Gabriel2 小时前
【微服务】认识微服务
java·微服务·架构
ThetaarSofVenice2 小时前
【Java从入门到放弃 之 Java程序基础】
java·开发语言·python
夏子曦2 小时前
java——Tomcat调优策略
java·开发语言·tomcat
夏子曦2 小时前
java——利用 Tomcat 自定义的类加载器实现热加载
java·tomcat
G丶AEOM2 小时前
Redis中HGETALL和ZRANGE命令
java·redis
In 20292 小时前
矩阵【Lecode_HOT100】
java·算法·矩阵
王·小白攻城狮·不是那么帅的哥·天文3 小时前
Spring框架使用xml方式配置ThreadPoolTaskExecutor线程池,并且自定义线程工厂
xml·java·spring·线程池