- Java NIO(non-blocking IO):从jdk1.4开始,Java提供的一系列改进输入输出的新特性;同步非阻塞。NIO相关的类都被放在java.nio包及其子包下【java.io包内容改写】
- Java NIO三大核心组件:Channel(管道)、Buffer(缓冲区)、Selector(选择器)》》提供了面向缓冲区(面向块)的编程
-
Java NIO的非阻塞模式:一个线程可以从某通道发送请求/读取数据——》得到目前可用的数据(无数据可用则什么都不获取)——》不会保持线程阻塞,线程可以做其他事情。【一个线程可以处理多个操作】
-
HTTP2.0使用了多路复用的技术(同一个连接并发处理多个请求)——》》并发处理的数量比HTTP1.1大好几个数量级。
【将数据读取到缓冲区中,并可以根据需要移动其前后位置》》增加了处理过程中的灵活性》》提供非阻塞的高伸缩性网络】
[注]:客户端将请求和数据发送到Buffer中暂存,Buffer直接与通道(Channel)进行交互,服务器线程通过选择器(Selector)轮询客户端请求并处理,选择器将通道请求上传之后并不需要阻塞等待服务器的处理结果,而是在此期间继续询问其他客户端有无请求。
Buffer的基本使用
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
public class BasicBuffer {
public static void main(String[] args) {
//举例说明Buffer的使用
//创建一个Buffer,大小为5,即可以存放5个int数据
IntBuffer intBuffer = IntBuffer.allocate(5);
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
//向Buffer中存放数据
for (int i=0; i<intBuffer.capacity();i++){
//intBuffer.capacity()方法:buffer的容量
/**
* Returns this buffer's capacity.
* */
//intBuffer.put()方法:向buffer中存放数据,一次放一个
/**
* <p> Writes the given int into this buffer at the current
* position, and then increments the position. </p>
* */
intBuffer.put(i*2);
}
//从buffer中读取数据,先进行读写状态切换
intBuffer.flip();
/**
* public final Buffer flip() {
* limit = position; 读数据不能超过position
* position = 0; position移动到开始位置
* mark = -1;
* return this;
* }
*/
/**
* Flips this buffer. The limit is set to the current position and then
* the position is set to zero. If the mark is defined then it is
* discarded.
*
*
* <p> This method is often used in conjunction with the method when transferring data from
* one place to another. </p>
*/
while (intBuffer.hasRemaining()){
System.out.println(intBuffer.get()); //intBuffer.get()方法维护了一个索引,每读取一个数据,索引后移一次
}
}
}
BIO和NIO的比较:
- BIO以流的方式处理数据,NIO以块的方式处理数据,块IO的效率比流IO高很多
- BIO是阻塞的,块IO是非阻塞的
- BIO基于字节流或字符流进行操作,NIO则基于Channel(通道)和Buffer(缓冲区)进行操作,数据总是从通道读入缓冲区或从缓冲区写入通道
- Selector(选择器)用于监听多个通道事件(连接请求,数据到达等)。故使用单个线程可以监听多个客户端通道。
Selector、Channnel和Buffer的关系
- 每一个Channel对应一个Buffer;每个Selector对应一个线程;一个线程可对应多个Channel【注】可理解为一个线程对应多个连接。
- 多个Channel可以注册到一个Selector程序;程序切换到哪个Channel是由事件(Event)决定的,Selector会根据不同的事件,在各个通道上切换。
- Buffer是一个内存块,其底层是由一个数组实现的;数据的读写是通过Buffer
- Channel是双向的,可以返回底层OS的情况,例如Linux底层的OS通道就是双向的。
【注】BIO中的数据读写要么是输入流,要么是输出流,不能双向;NIO的Buffer既可以读也可以写,但需要使用flip()方法切换状态。