一 NIO
1.1 介绍
1.NIO:为同步非阻塞。位于java的 java.nio.*包下,NIO三大核心部分:
- Channel 通道
- Buffer 缓冲区:底层使用Unsafe类直接操作内存,Buffer中写入的所有数据jvm都不进行管理,不能被gc回收。
- Selector 选择器
2.NIO是面向缓冲区的。当数据读取到一个它稍后处理的缓冲区,需要时可在缓存区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络。
3.通俗讲NIO的同步非阻塞:NIO是可以做到用一个线程来处理多个操作的,假设有10000个请求过来,根据实际情况,可以分配50个或者100个线程来处理,不像之前的阻塞IO那样,非得1000个。
其中http2.0采用多路复用技术,做到同一个连接并发处理多个请求,而且并发请求的数量比http1.1大了好多个数量级。
1.2 Buffer的简单操作案例
package com.ljf.netty.nio;
import java.nio.IntBuffer;
/**
* @ClassName: BufferDemo
* @Description: TODO
* @Author: liujianfu
* @Date: 2022/05/12 22:37:50
* @Version: V1.0
**/
public class BufferDemo {
public static void main(String[] args) {
IntBuffer intBuffer=IntBuffer.allocate(5);
for(int k=0;k<intBuffer.capacity();k++){
intBuffer.put(k*30);
}
//读取数据,将写切换成读模式
intBuffer.flip();
while(intBuffer.hasRemaining()){
System.out.println("读取:"+intBuffer.get());
}
}
}
结果:

1.3 flip()方法的作用

1.4 BIO和NIO的区别
BIO是阻塞的,NIO则是非阻塞的。
BIO是以流的方式处理数据,而NIO是以缓存区(缓存块)的方式处理数据,缓存块的I/O效率比流的I/O效率高很多。
BIO基于字节流和字符流进行操作,而NIO基于channel(通道)和Buffer(缓存区)进行操作,数据总是从通道读取到缓存区中,或者从缓冲区写入到通道中。
selector(选择器)用于监听多个通道的事件(比如:连接请求、数据到达等),因此使用单个线程就可以监听多个客户端通道。
1.5 NIO的3大组件核心关系
1. 1个selector对应一个线程,一个线程对应多个channel。1:n关系。
2.每个channel都会对应一个Buffer。1:1关系
3.selecotr会根据不同的事件,在各个通道上进行切换
4.Buffer就是一个内存块,底层是一个数组,数据的读取写入都是通过Buffer。其中BIO中要么是输入流,要么是输出流,不能双向。但是NIO的Buffer是可以读也可以写的。需要flip方法切换。
5.channel是双向的,可以返回底层操作系统的情况,比如linux,底层的操作系统。

二 NIO的buffer
2.1 buffer
缓存区(Buffer):缓存区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,缓存区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化请,channel提供从文件、网络读取数据的渠道。但是读取或写入的数据都必须经由buffer,如图

2.2 常见缓存区类型
1.在NIO中,buffer是一个顶层父类,它是一个抽象类。常用的子类
ByteBufer: 存储字节数据到缓存区
ShortBuffer:存储字符串数据到缓存区
CharBuffer:存储字符数据到缓存区
IntBuffer:存储整数数据到缓存区
LongBuffer:存储长整型数据到缓冲区
DoubleBuffer:存储小数到缓冲区
FloatBuffer:存储小数到缓存区。
注意可以看出:java中的基本数据类型(boolean)除外,都有一个Buffer类型与之对应。
2.3 缓存区重要方法属性

2.4 常见方法属性
数学关系:-1<= mark <= positon <= limit <= capacity
mark: 标记着当前position可读或可写的索引值
position:指向下一次可读或者可写的索引值
limit:可读可写的索引一定是小于它的,不能等于它
capacity:数组容量,一旦初始化好了,便永远无法修改

mark方法:标记将开始可操作位置索引标记一下,
reset方法:将之前标记的位置索引,重新赋值给可操作位置索引。

三 NIO的通道
3.1 NIO的通道与普通数据流的区别
1.Nio的通道类似流,但是可以同时进行读写,而流只能读或者只能写,例如BIO的stream是单向的,FileInputStream对象只能进行读取数据操作。
2.通道可以实现异步读写数据,可以从缓存读数据,也可以写数据到缓存中。
3.channel是NIO的一个接口,常见的有filechannel,Datagramchannel,serversocketchannel等
4.FileChannel用于文件的数据读写,DatagramChanel用户udp的数据读写,
serversocketChannel和socketchannel用于Tcp的数据读写。
3.2 常见方法的作用
public int read(ByteBuffer dst): 从通道读取数据并放到缓存区中。
public int write(ByteBuffer src):把缓存区的数据写到通道中。
public long transferFrom(ReadableByteChannel src,long position,long cout):从源通道中复制数据到当前通道。
public long transferTo(long position,long cout,ReadableByteChannel dst):从当前通道复制数据到目标通道
3500

被折叠的 条评论
为什么被折叠?



