最近想做一个开源的IM组件,在IO的选型上必定要选择NIO,于是翻了翻资料总结了一下传统IO与NIO的一些区别,从而了解IM系统为什么一定需要用到NIO.
下面是对NIO的一些简单的介绍
NIO弥补了原来同步阻塞I/O的不足,它在标准Java代码中提供了高速的、面向块的I/O。
Java NIO 由以下几个核心部分组成:
Channel
Buffer
Selector
传统IO与NIO的一些区别
传统IO 和 NIO 的区别主要体现在三个方面:
(1)传统IO 基于输入流、输出流来做的(Stream),而 NIO 基于 Buffer (Buffer);
(2)传统IO 操作是阻塞的,而 NIO 操作是非阻塞的;
(3)传统IO 没有 selector 概念,而 NIO 有 selector 概念.
传统IO 是面向字节流或字符流的,在一般在操作的时候,我们以流式的方式顺序地从一个 Stream 中读取一个或多个字节,所以我们也就不能随意改变读取指针的位置,必须从头到尾。而在 NIO 中,而是引入了 Channel 和 Buffer 的概念。在 NIO 中,只需要从 Channel 中读取数据到 Buffer 中,将数据从 Buffer 中写入到 Channel。这里的Channel就替代了我们之前的输入流与输出流。并且,不像传统IO 那样是顺序操作,在NIO 中,我们可以随意地读取任意位置的数据.
什么是Selector
这是一个IO事件的查询器,通过 Selector,一个线程可以查询多个 Channel 的 IO 事件的就绪状态。
我们要做的工作,就是将要进行状态查询的Channel(相当于之前的操作的输入流与输出流这两个流的结合)注册到选择器Seletor中。当我们向一个 Selector 中注册了 Channel 后,Selector 内部的机制就可以自动地为我们不断地查询(select) 这些注册的 Channel 是否有已就绪的 IO 事件(例如可读,可写,网络连接完成等)。
通过这样的 Selector 机制,我们就可以很简单地使用一个线程高效地管理多个 Channel 了。
什么是Buffer
Buffer的作用就是在与 NIO Channel 进行交互时,我们就需要使用到 NIO Buffer,即数据从 Buffer读取到 Channel 中,并且从 Channel 中写入到 Buffer 中。
最后解释一下什么是阻塞与非阻塞(这也是面试常问的)
Java 传统IO提供的各种 stream 流操作都是阻塞的,我们调用一个 read 方法去读取某个文件时,那么调用 read 的这个线程会被阻塞住,一直到 read这个操作完成。
而 NIO 的非阻塞模式允许我们非阻塞地进行 IO 操作。 例如我们需要读取数据。在 NIO 的非阻塞模式中,当我们调用 read 方法时,如果此时有数据,则 read 读取并返回; 如果此时没有数据,则 read 直接返回,而不会阻塞当前线程。NIO如何做到的就是因为引入了Selector与Channel多路复用