【面试官】那Java NIO为什么速度快?
- 面试官:了解过NIO吗?
- 面试官:那NIO为什么速度快?
- 面试官:还有吗?
- 面试官:你刚刚说输入/输出流是处理字节?字符流不是处理字符吗
- 面试官:你具体介绍下Buffer
- 面试官:Channel呢?
- 面试官:知道NIO零拷贝吗?
- 👉以贴近现实的【面试官面试】形式涵盖大部分Java程序员需要掌握的后端知识、面试问题
- 📚本期是《Java IO系列》,其他系列博客请订阅专栏《后端训练营》
- ❤创作不易,不妨点赞、收藏、关注支持一下
文章目录
- Java NIO
- 通道和缓冲器
- 非阻塞IO模型
- 字符流处理字符?
- Channel和Buffer使用
- Buffer
- Channel
- NIO零拷贝
1. Java NIO
面试官:了解过
NIO
吗?
了解的面试官。NIO的出现在于提高IO
的速度,它相比传统的输入/输出流速度更快。
NIO通过管道Channel
和缓冲器Buffer
来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。
程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
1.1 通道和缓冲器
面试官:那
NIO
为什么速度快?
是这样的,NIO提供了通道和缓冲器这两个核心对象。
(1)管道Channel
:
与传统的IO
流只能只读或只写的单向流不同,NIO通道是双向的,也就是说读写操作可以同时进行,使得数据的处理效率也更高。
(2)缓冲器Buffer
:
传统的输入/输出流一次只处理一个字节,而每一次字节读取都是一次系统调用,涉及到用户空间和内核空间之间的上下文切换,通常来说效率不高。
而NIO
采用内存映射文件方式来处理输入/输出,Channel通过map()
方法把一块数据映射到内存中。程序通过Buffer
进行数据交互,减少了与原始数据源的直接访问。NIO面向块的处理方式使得效率更高。
1.2 非阻塞IO模型
面试官:还有吗?
有的。
传统的输入/输出流是同步阻塞IO
模型,如果数据源没有数据了,此时程序将进行阻塞。
而NIO
是I/O多路复用模型,线程可以询问通道有没可用的数据,而不需要在没有数据时阻塞掉线程。
1.3 字符流处理字符?
面试官:你刚刚说输入/输出流是处理字节?字符流不是处理字符吗?
不是的。所有数据包括文本数据最终都是以字节形式存储的,因为计算机底层只能理解二进制数据。
字符最终也是要转换成字节形式,之所以可以在文本文件看到字符,是因为系统将底层的二进制序列转换成了字符。
2. Channel和Buffer
使用
2.1 Buffer
面试官:你具体介绍下Buffer?
好的,Buffer里有3个关键变量。
- capcity:表示缓冲器
Buffer
的最大数据容量。 - position:用来指出下一个可以读出/写入
Buffer
的索引位置,也就是记录指针的作用。 - limit:用来表示在
Buffer
里第一个不能被读出/写入的索引位置。
另外Buffer
还提供了get
、put
方法来供我们操作数据,而使用get/put
后,position的指针位置也会随之移动。
public abstract byte get();
public abstract ByteBuffer put(byte b);
2.2 Channel
面试官:Channel呢?
Channel有常见的3个方法,map()、read()和write()。
// 将通道文件的区域直接映射到字节缓冲区中
public abstract MappedByteBuffer map(MapMode mode, long position, long size)
// 从此Channel通道读取字节序列到给定缓冲区dst
public abstract int read(ByteBuffer dst)
// 将给定缓冲区中src的字节序列写入此Channel通道
public abstract int write(ByteBuffer src)
以下是Channel
的简单使用代码。
public class TestFileChannel {
public static void main(String[] args) {
File f = new File("D:\\JavaGetOffer\\TestFileChannel.java");
try {
FileChannel inChannel = new FileInputStream(f).getChannel();
FileChannel outChannel = new FileOutputStream("a.txt").getChannel();
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
outChannel.write(buffer);
buffer.clear();
CharBuffer charBuffer = StandardCharsets.UTF_8.newDecoder().decode(buffer);
System.out.println(charBuffer);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
3. NIO零拷贝
面试官:知道
NIO
零拷贝吗?
是这样的,在NIO
零拷贝出现之前,一个I/O操作会将同一份数据进行多次拷贝。一次I/O操作对数据进行了四次复制,同时来伴随两次内核态和用户态的上下文切换,众所周知上下文切换是很耗费性能的操作。
而零拷贝技术改善了上述的问题。零拷贝技术减少了对一份数据的拷贝次数,不再需要将数据在内核态和用户态之间进行拷贝,也意味不再进行上下文切换,让数据传输变得更加高效。
未完待续。。。
好了,今天的分享就先到这,我们下期《Java IO系列》继续。
#大厂##大厂面试##Java面试##Java##后端#📚以贴近现实的【面试官面试】形式涵盖大部分Java程序员需要掌握的后端知识、面试问题,其他系列博客请订阅专栏《后端训练营》
创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️❤️
👉以贴近现实的【面试官面试】形式帮助你系统学习后端技术 👉成体系知识帮你在后端进阶,每一道问答助你怒怼大厂面试官,收获大厂offer 👉《后端训练营》包含Redis系列、MySQL系列、Kafka系列、ZooKeeper系列、JVM系列、多线程系列等等 👉制作不易,各位的支持是我创作的最大动力