在 JDK1.4 之后,为了提高 Java IO 的效率,Java 又提供了一套 New IO(NIO),原因在于它相对于之前的 IO 类库是新增的。此外,旧的 IO 类库提供的 IO 方法是阻塞的,New IO 类库则让 Java 可支持非阻塞 IO,所以,更多的人喜欢称之为非阻塞 IO(Non-blocking IO)。
一、NIO网络模型
1、NIO网络模型猜想?
- Acceptor:接受客户端连接请求。
- 当客户端有连接请求之后,服务端会创建一个scoket,将它放入一个set集合中,然后遍历这个set集合,一直调用read方法,当read方法没有数据返回或者返回空的时候,说明没有数据到达,就不用去处理,当read方法返回有数据说明请求到客户端请求过来的连接,这时候就会调用handler方法来处理具体的业务员逻辑。
- 多个客户请求过来都会放在set集合中,handler一个方法来一次处理所有的客户端请求。
2、具体的请求过程
第一步:
在选择器上注册建立连接事件
第二步:
当客户端向服务端发送建立连接请求时,selector就会检测到这个连接请求的事件,然后selector就会建立启动一个建立连接事件的处理器。
第三步:
然后与客户端创建一个scoket的连接,并且响应客户端成功的请求,然后acceptor hander方法会将新创建的scoket的连接注册到selector,并且注册read事件也就是可读事件
第四步:
当客户发送请求到服务端,这时候selector就会监听到它的一个可读事件,这时候selector就会启动一个连接读写处理器,然后通过read&write Handler方法响应客户端的请求,返回给客户端,这时候还会将注册的连接可读事件 注册到selector上。
selector:多路复用选择器,它是一个核心,它的主要功能就是接受所有的与客户端建立的scoket连接,并且监听他们所关心的事件,当这个事件发生之后,就会调用相应的事件处理器来处理这个事件。
二、NIO网络编程详解
NIO的核心类
- Channel:通道
- Buffer:缓冲区
- Selector:选择器或多路复用器
1、Channel(通道)
Channel的特性:
- 双向性
- 非阻塞性
- 操作唯一性(只能通过buffer来操作)
Channel实现类:
文件类,
UDP类,
TCP类
Channel通道的具体使用:
2、Buffer(缓冲区)
作用:读写Channel中的数据
本质:一块内存区域
(1)、buffer属性
- Capacity:容量
- Position:位置
- Limit:上限
- Mark:标记
(2)、buffer的使用(也就是围绕这个4个属性变化的过程)
3、Selector(选择器或多路复用器)
作用:I/O就绪选择
地位:NIO网络编程的基础
(1)、selector的使用
三、BIO与NIO对比
IO模型 | IO | NIO |
---|---|---|
方式 | 从硬盘到内存 | 从内存到硬盘 |
通信 | 面向流(乡村公路) | 面向缓存(高速公路,多路复用技术) |
处理 | 阻塞IO(多线程) | 非阻塞IO(反应堆Reactor) |
触发 | 无 | 选择器(轮询机制)
|
1、面向流与面向缓冲:
Java NIO和IO之间第一个最大的区别是,IO是面向流的.NIO是面向缓冲区的。Java IO面向流意味着毎次从流中读一个成多个字节,直至读取所有字节,它们没有被缓存在任何地方,此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的教据,需要先将它缓存到一个缓冲区。Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,霱要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数裾。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
2、阻塞与非阻塞:
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
3、选择器(Selector):
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择"通道:这些通里已经有可以处理的褕入,或者选择已准备写入的通道。这选怿机制,使得一个单独的线程很容易来管理多个通道。
4、NIO和BIO读取文件:
BIO读取文件:链接。
BIO从一个阻塞的流中一行一行的读取数据。
5、处理数据的线程数:
NIO:一个线程管理多个连接
BIO:一个线程管理一个连接