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); }