IO和NIO的本质与区别


1、IO的本质

  要了解IO和NIO,我们先从计算机原理上来看一下IO是什么?

    IO本质上就是对内存的操作,将数据流写入内存就是Input,从内存写出数据流就是Output。

    IO有五种模型:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO。

  我们来看下Java应用程序在系统中的IO是什么样的?

    系统分为用户空间和内核空间,Java应用运行在用户空间,因为对所有外部数据的处理都是由系统内核来实现的,对于Java应用程序来说,只是调用操作系统中相应的接口方法,从而和外部数据进行交互。

  说完这一点我们再了解两个概念:DMA(也叫协处理器)和虚拟地址空间

  DMA其实就是替CPU分担IO操作的,因为IO会存在较多的等待时间,所以由DMA来处理IO操作,从而让CPU更多地去处理计算任务。

  虚拟地址空间:是实际物理地址的映射,是为了不同程序之间的互相隔离和保证程序中地址的确定性。

2、IO和NIO的区别

    先看下二者主要区别:

IO NIO
面向流 面向缓冲
阻塞 非阻塞
选择器

(1)面向流与面向缓冲

  Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,数据没有被缓存在任何地方。此外,它不能前后移动流中的数据。Java NIO将数据读取缓冲区,可以更方便地处理数据。

(2)阻塞与非阻塞

  Java IO中,当一个线程调用 read() 或 write() 方法时,该线程会被阻塞,直到完成数据的读取或写入。Java NIO的非阻塞模式,使一个线程从一个通道来读写数据,有数据就读取,没有也不会阻塞而是可以处理其他逻辑。写数据时不用等到完全写入,写的时候也可以处理其他逻辑。线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道。

(3)选择器(Selector)

  Java NIO的选择器允许一个单独的线程来监视多个输入通道,可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

3、IO和NIO的使用

(1)IO的使用

  Java IO中分为DataOutPut和DataInPut,分别对应IO的out和in。

  DataOutPut有三大类,分别是Writer,OutputStream和ObjectOutput。

  DataInput也有三大类,分别是ObjectInput,InputStream和Reader。

InputStream input = ... ; // 磁盘流或网络流   

BufferedReader reader = new BufferedReader(new InputStreamReader(input));   

String nameLine   = reader.readLine(); 

(2)NIO的使用

  Java NIO需要将数据通过通道读取到缓冲区中。

ByteBuffer buffer = ByteBuffer.allocate(48);   

int bytesRead = inChannel.read(buffer);   

while(! bufferFull(bytesRead) ) {   
       bytesRead = inChannel.read(buffer);   
}