这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
前言
大家好,我是程序猿小白 GW_gw,很高兴能和大家一起学习进步。
以下内容部分来自于网络,如有侵权,请联系我删除,本文仅用于学习交流,不用作任何商业用途。
摘要
本文主要带大家了解什么是NIO,以及NIO中Buffer的简单介绍。
NIO
1. NIO简介
NIO(New IO)也就是新IO的简写,当我们使用原始IO流对数据的读写往往是阻塞的,并且是面向流的,一个字节一个字节进行处理,往往效率不高,因此JDK1.4开始,java提供了java.nio包,对之前的java.io中的很多类进行了改写,以提高性能。
简单做一下传统IO和NIO的对比。
| IO | NIO |
|---|---|
| 面向流 | 面向缓冲区 |
| 阻塞 | 非阻塞 |
在NIO中有两个核心对象:Channel(通过)和Buffer(缓冲)。
在NIO中所有的数据都需要通过Channel进行传输,就像传统IO的InputStream和OutputStream,但是Channel提供了map方法,可以操作"一块数据"。
Buffer就像是一个容器,用来存放将要通过通道传输的数据,或者获取通过通道传输过来的数据。
2. Buffer
Buffer是一个抽象类,用于存放特定原始类型的数据的容器。常用的子类有两个,分别是ByteBuffer和CharBuffer。还有一些其他基本数据类型对应的Buffer子类,都是XXXBuffer的形式。这些类也都是一些抽象类,但是为我们提供了静态方法来获取实例对象。
以ByteBuffer为例,来看源码:
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
这两个方法的区别是,一个为我们创建非直接字节缓冲区,一个为我们创建直接字节缓冲区。那什么是直接字节缓冲区,什么是非直接字节缓冲区呢?
直接字节缓冲区:
在虚拟机内存外开辟的内存,直接执行本地I / O操作,避免在每次I / O操作之前(或之后)将缓冲区的内容复 制到中间缓冲区。
优点:少了一次复制操作,读写速度快,大约是使用非直接字节缓冲区的5倍。
缺点:占用CPU的开销,如果文件过大,可能会导致电脑卡死。
非直接字节缓冲区:
在虚拟机内存中开辟的区域,需要将内容复制到临时缓存中才能进行IO操作。
优点:在虚拟机中创建,易于销毁。
缺点:处理过程中有复制操作,速度较慢,占用JVM内存开销。
通常情况下我们会在使用直接字节缓冲区能为程序带来较好的性能时才使用,一般使用非直接字节缓冲区即可。
对于是字节缓冲区的类型我们可以通过isDirect()方法来确定。
public abstract boolean isDirect();
具体子类会实现该抽象方法,根据缓冲区类型返回true或false。
在Buffer中有三个重要参数:capacity(容量)、limit(界限)、position(位置)。
capacity(容量):表示该缓冲区能容纳的最大数据量,不能为负值,且创建后不能更改。
limit(界限):在limit之后的数据不能读也不能写。
position(位置):表示下一个可以读写的缓冲区位置索引(默认从0开始)。
除了以上三个参数外还有一个mark标记,可以直接将position的位置指向mark。
大小关系如下:
0 <= mark <= position <= limit <= capacity
小结
以上就是关于NIO的一些简单入门介绍,希望能对读者有所帮助,如有不正之处,欢迎留言指正。