NIO

1. 前言

 JDK 1.4 中新加入了NIO( New Input/ Output) 类, 引入了一种基于通道和缓冲区的 I/O 方式它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在

 Java堆的 DirectByteBuffer 对象作为这块内存的引用进行操作,避免了在 Java 堆和 Native 堆中来回复制数据。NIO 是一种同步非阻塞的 IO 模型。

 同步是指线程不断轮询 IO 事件是否就绪,同步的核心就是 Selector,Selector 代替了线程本身轮询 IO 事件,避免了阻塞同时减少了不必要的线程消耗;

 非阻塞是指线程在等待 IO 时可以同时做其他任务。非阻塞的核心就是通道和缓冲区,当 IO 事件就绪时,可通过写到缓冲区保证 IO 的成功,无需线程阻塞式地等待。

2. Buffer

 buffer即为缓冲区,用于数据储,底层用数组存储,存储的元素类型为基本类型,Buffer针对JAVA8个基本数据类型,提供了7个子类型(除了boolean类型)

 因为boolean类型可以通过规定1为true,0为false来实现存储boolean类型,不影响使用,7个子类型最常用的是byteBuffer,因为计算机数据传输以字节形式;

2.1 参数概念

capacity: 容量位,记录缓冲区的容量,初始化指定后不可变;

limit: 限制位, 用于标记操作位能到达的最大位置,新建一个buffer,limit默认在最后一位,和capacity指向同一个位置;

position: 操作位,指向操作的位置,默认在第零位

mark:标记位,用于数据的校验,在java中mark位默认不启用,值为-1;

2.2 主要方法

allocate:分配固定大小的buffer流数组;

wrap:动态非陪buffer流数据;

flap:反转缓冲区,将limit位移到postion位,然后将postion位归零;

clear: 清空缓冲区,回归原始状态(postion=0, limit = capacity mark = -1);

reset: 重置缓冲区,将postion移动到mark标记位上,防止错误;

rewind:重绕缓冲区,将postion归零,mark置为-1,用于重新遍历ByteBuffer流;

2.3 基本用法

使用Buffer读写数据一般遵循以下四个步骤:

1. 写入数据到Buffer

2. 调用flip()方法将Buffer模式切换到读模式

3. 从Buffer中读取数据

4. 调用clear()方法或者compact()方法清空缓存区

3. Channel

 Channel用于数据输,它是双向通道,可实现双向数据传输

 针对文件:FileChannel

 针对UDP:DatagramChannel

 针对TCP: SocketChannel、ServerSocketChannel

如下图(单机版):理论上客户端可以收到服务端写回客户端的信息“message got”,但是实际上往往获取不到,主要原因如下

1. 因为此时客户端和服务端都是非阻塞,客户端在发送完信息到服务端后,继续执行,还没有来得及收到服务端返回的信息,客户端已经关闭流;

2. 针对第一点,可以在客户端在发送完数据到服务端之后,Thread.sleep()来等待服务器端返回信息,此时又面临一个问题,客户端在等待的时候,服务端已经关闭流;

3.而上述问题,无法通过编程来精确实现,因为用户客户端发送的数据量未知,基于以上两点原因,引出Selector组件;

4. Selector

 Selector 选择器(多路复用器) 用于检查 Channel的状态是否处于可读、可写,可以实现单线程管理多个channels,实现管理多个网络链接;

5. NIO框架

Netty

原文地址:https://www.cnblogs.com/oxygenG/p/12635464.html