Java中的NIO和IO的比较

        java标准的I/O中,提供了基于流的I/O实现,即InputStream和OutputStream。这种基于流的实现以字节为单位处理数据。

        NIO在java 1.4中被纳入到了JDK中,与旧式的的基于流的I/O相比,NIO是基于块的,以块为单位处理数据。NIO有两个重要的组件缓冲(Buffer)和通道(Channel)。

        Buffer:缓冲是一块连续的内存块,是NIO读写数据的中转池。

        Channel:通道主要用于向缓冲读取和写入数据,是访问缓冲的接口。

       NIO是为了弥补IO操作的不足,NIO的一些新特性有:非阻塞I/O,缓冲,管道以及选择器。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。

Buffer和Channel:

    在NIO的实现中,Buffer是一个抽象类。JDK为每一种java基本数据类型(除了Boolean)提供了缓冲区类型。    

缓冲区类型
缓冲区类型 基本数据类型
ByteBuffer byte
CharBuffer char
ShortBuffer short
IntBuffer int
LongBuffer long
FloatBuffer float
DoubleBuffer double

在NIO中,Buffer必须配合Channel使用。比如在读取一个channel的时候,需要先将数据写入到相应的Buffer,然后再Buffer中读取。

以一个读文件为例:

// 首先将文件打开,取得文件的Channel:
FileInputStream  inputStream = new FileInputStream ( new File( "d:\\temp_buffer.txt"));
FileChannel fc = inputStream.getChannel();

// 要从文件Channel中读取数据,必须使用Buffer.
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
fc.read(byteBuffer);

// 此时,文件内容以及存在于Buffer中,准备读取ByteBuffer.
byteBuffer.flip();

Buffer的基本原理:

Buffer有三个重要的参数:位置(position)、limit(上限)、capacity(容量)。

Buffer参数的含义
参数 写模式 读模式
位置(position) 当前缓存区的位置,将从position的下一个位置写数据 当前缓冲区读取的位置,将从此位置后,读取数据
capacity(容量) 缓存区的总容量上限 缓存区的总容量上限
limit(上限) 通常情况下,和容量相同。小于等于容量 可读取的总容量,和上次写入的数据量相等

Buffer的创建:

    Buffer的创建有两种方式:

        1.静态allocate()从堆中分配缓冲区

        2.从一个既有数组中创建缓冲区

//  从堆中分配
ByteBuffer buffer = ByteBuffer.allocate(1024);

//  从既有数组中创建
byte[] array = new byte[1024];
ByteBuffer buffer = ByteBuffer.wrap(array);

重置缓冲区:

    Buffer提供了重置Buffer的函数。

public  final  Buffer flip()
    函数flip()先将limit设置到position所在位置,然后将position置零,并清除标志位mark。通常在读写转换时使用。


NIO和传统的IO有什么区别呢?

1、IO是面向流的,NIO是面向块(缓冲区)的。

    IO面向流的操作一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。,导致了数据的读取和写入效率不佳;

    NIO面向块的操作在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多,同时数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。

    通俗来说,NIO采取了“预读”的方式,当你读取某一部分数据时,他就会猜测你下一步可能会读取的数据而预先缓冲下来。

2、IO是阻塞的,NIO是非阻塞的。

    对于传统的IO,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。

    而对于NIO,使用一个线程发送读取数据请求,没有得到响应之前,线程是空闲的,此时线程可以去执行别的任务,而不是像IO中那样只能等待响应完成。

猜你喜欢

转载自blog.csdn.net/qq994406030/article/details/80298049