【Java 总结思考】Java 答疑解惑之 IO 篇

打破舒适圈,经常对 Java 知识进行总结思考,才能保证自己不掉队。

系统化重学 Java 第四篇,这一次,轮到 IO 了。


第一问: 信息的最小存储单元是字节,为什么 IO 流操作要分为字节流操作和字符流操作呢?

字符流是由 Java 虚拟机转换字节得到的,这个过程非常耗时,并且如果不知道编码类型还很容易出现乱码问题。

所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。

如果是音频文件、图片等媒体文件直接用 字节流  处理,如果涉及到字符的话就使用 字符流


 第二问: 什么是 NIO ,NIO 中的 Channel 和 IO 流的区别?

NIO 是一个同步非阻塞 IO,支持一个线程处理多个客户端请求,它的核心概念有 Buffer,Channel,Selector。

下图是 NIO 模型的基本架构图:

Selector 是中央控制器,Buffer 是承载数据的容器,而 Channel 可以说是一个通信桥梁,通过这座桥梁,数据才能被写入Buffer,连接才能被 Selector 控制。

NIO 中的 Channel 和 IO 流的区别有:

  • Channel 是双向的,可读可写;而 I/O 流是单向的;
  • Channel 总是基于缓冲区 Buffer 进行读写的;
  • Channel 可以异步读写;

 第三问: NIO 适用于什么样的使用场景?

对于低负载、低并发的应用程序,没必要使用 NIO,使用同步阻塞 IO 反而可以提升开发速率,实现更好的维护性;

而对于高负载、高并发的(网络)应用,推荐使用 NIO 的非阻塞模式来开发。


第四问: NIO 和 NIO2 的区别是什么?

NIO

从 JDK1.4 开始,Java 提供了一系列改进的 IO 处理的新特性,被统称为 NIO(New I/O) 。

它新增了许多用于处理输入输出的类,这些类都被放在 java.nio 包及子包下,并且对原 java.io 包中的很多类进行改写,用于满足 NIO 的功能。

NIO 和原始 IO 最大的区别在于,原来的 IO 以 流的方式 处理数据,而 NIO 以 块的方式 处理数据。这种方式相对来说处理速度更快,但是一定程度上不那么灵活,失去了优雅性和简单性。

NIO 2

在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。

异步 IO 操作基于 事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。


第五问: 为什么 Netty 使用 NIO ,而不使用 NIO2 ?

  • Netty 不看重 Windows 上的使用,在 Linux 系统上,NIO2 的底层实现仍使用 EPOLL,性能上没有明显优势,而且被 JDK  封装了一层,不容易深度优化;
  • Netty 整体架构是 reactor 模型,而 NIO2 是 proactor 模型,混合在一起非常混乱,而如果把 NIO2 改造成 reactor 模型又会很麻烦,看起来是把 epoll 绕个弯又绕回来;
  • NIO2 在接收数据时,需要预先分配缓存;而 NIO 是在需要接收时才会分配缓存,所以 NIO2 对连接数非常大但流量小的情况下,会导致内存的严重浪费;
  • 在 Linux 上 NIO2 不够成熟,处理回调结果速度跟不上需求处理速度;

来源链接:https://www.jianshu.com/p/df1d6d8c3f9d


 第六问:NIO 是如何实现零拷贝的?

在网络编程中,通常由 read、write 来完成一次 IO 读写操作。每一次 I/O 读写操作都需要完成四次内存拷贝,如下图所示。 

常见的零拷贝是 Linux 支持的零拷贝,它是通过 Linux 内核中的 mmap 函数来实现的。

这个函数可以代替 read、write 的 IO 读写操作,实现用户空间和内核空间共享一个缓存数据。

它将用户空间的一块地址和内核空间的一块地址同时映射到相同的一块物理内存地址,不管是用户空间还是内核空间都是虚拟地址,最终通过地址映射将虚拟地址映射到物理内存地址。这种方式避免了内核空间与用户空间的数据交换。

在 Java 的 NIO 编程中,则是使用到了 DirectBuffer 来实现内存的零拷贝。DirectBuffer 是 NIO 提供的一个可以直接访问物理内存的类 。

普通的 Buffer 分配的是 JVM 堆内存,而 DirectBuffer 是直接分配物理内存(非堆内存),这样内核和用户进程都能共享一份缓存数据。

具体的零拷贝的实现可以参考这篇文章:

https://juejin.cn/post/6863264864140935175


如果在看的小伙伴有关于 IO 方面的问题,欢迎评论区留言,我们一起寻找答案,共同进步!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盛夏温暖流年

可以赏个鸡腿吃嘛~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值