Java NIO与IO的区别
基本区别
IO | NIO |
---|---|
Stream Oriented | Buffer Oriented |
Blocking IO | NIO Blocking IO |
Selector |
Stream Oriented vs Buffer Oriented
Stream Oriented | Buffered Oriented |
---|---|
面向流表示你可以每次读取一个字节或者读取多个字节到byte数组中,不能向前或向后移动数据,没有数据缓存 | 面向缓存表示每次读取多个字节到buffer中,可在缓存中对数据进行向前或向后移动操作,有缓存 |
Blocking IO vs Non-Blocking IO
Blocking IO | Non-Blocking IO |
---|---|
阻塞iIO即每次read或write方法调用都将等到外设可读取数据并读取数据同时返回,或者等到外设可写入数据并将数据写回外设之后方法调用才会返回 | 非阻塞IO指read/write方法调用会立即返回,而不用等到外设已经准备完毕才返回,而是等外设准备就绪之后进行回调,通过这样的方式让cpu达到更高的利用率 |
Selector
Java NIO Selector允许一个单独的线程去监控所有Channel的状态。你只需要将Channel注册到Selector上同时指定关注的事件类型,当Selector监控到Channel的状态有变化时,会更新Selector中的readyKey,这样当你就只需要一个线程去不断的查看Selector中所有注册了的channel的状态,对已经就绪的所有channel进行数据处理。
为什么需要引入Channel呢
我们知道java普通IO使用数据流(Stream-Inputstrea/OutputStream)对数据进行读取和写入,那我们为什么需要引入Channel呢?
1.Channel是双向的,可以对数据进行读取和写入操作
2.Stream主要是面向字节或字节流的,不具有缓存功能,这样就没办法往前或往后移动数据。
所以我们引入了Channel和Buffer,这样我们既实现了内存与外设之间的双向通道,同时也可以使用Buffer来对数据进行缓存。
为什么需要引入Selector呢?
如果没有Selector,我们对数据的读取和写入还是阻塞的,这样就会浪费cpu的资源,同时对于每个Channel,我们都得使用一个线程对外设进行操作来提高响应数据,所以我们引入了Selector,有了Selector,我们的Channel将自己感兴趣的事件(connect/accept/read/write)告诉Selector,Selector会轮询的检测所有注册了的Channel相关的事件是否已经准备就绪,如果已经就绪,则更新Channel中的状态,当我们通过代码调用Selector.select()方法时,如果有一个或多个Channel已经准备就绪,则会返回相应的结果,这时我们就可以通过另外的线程对数据进行读取和写入了。