Netty开篇——NIO章上(三)

Java NIO基本介绍

  1. java non-blocking I/O 称为NIO(也叫New IO)。JDK4开始提供,同步非阻塞
  2. 相关内容在 java.nio 包及子包下,对java.io 包中的很多类进行改写。
  3. 三大核心: Channel(通道),Buffer(缓冲区),Selector(选择器)
  4. NIO是面向缓冲区或者面向块 编程 。数据读取到一个它后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络
  5. NIO的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据可以读取之前,该线程可以继续做其他的事情。
  6. 通俗理解: NIO 是可以做到用一个线程来处理多个操作。假设有 10000 个请求过来,根据实际情况,可以分配50 或者 100 个线程来处理。不像之前的阻塞IO 那样,非得分配 10000 个。
  7. HTTP2.0 使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比 HTTP1.1 大了好几个数量级
  8. 基本案例:

NIO 和 BIO 的比较

  1. BIO以流的方式处理数据,而NIO以块的方式处理数据,I/O块的效率比I/O流高很多
  2. BIO 是阻塞的,NIO则是非阻塞的
  3. BIO 基于字节流和字符流进行操作,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector 选择器用于监听多个通道的事件(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道

Selector、Channel 和 Buffer 的关系图

  1. 每个channel都会对应一个Buffer
  2. 一个Selector对应一个线程
  3. 多个channel会注册到其selector
  4. Selector会根据不同的Event,在各个Channel上切换
  5. channel 是双向的,可以返回底层操作系统的情况,比如Linux,底层的操作系统通道就是双向的.
  6. Buffer是一个内存块,底层是一个数组
  7. 数据的读取写入是通过 Buffer,这个和BIO有所区别,BIO 中要么是输入流,或者是输出流,不能双向,但是NIO的Buffer是可以读也可以写,需要flip()切换

缓冲区(Buffer)

  1. Buffer本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,Buffer对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况。Channel 读写的数据都必须经由Buffer

  2. Buffer是父类、抽象类,类的层级关系图

  3. 常用Buffer子类

    • ByteBuffer 存储字节数据到缓冲区
    • shortBuffer 存储字符串数据到缓冲区
    • CharBuffer 存储字符数据到缓冲区
    • IntBuffer 存储整数数据到缓冲区
    • LongBuffer 存储长整型教据到缓冲区
    • DoubleBuffer 存储小数到缓冲区
    • FloatBuffer 存储小数到缓冲区
  4. 这些Buffer都把数据存于自己类型的数组

  5. Buffer类的四个属性:

    • Capacity:容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
    • Limit:表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的
    • Position:位置,下一个要被读写的元素的索引,每次读写缓冲区数据时都会改变改值,为下次读写做准备
    • Mark:标记

Buffer类相关方法

java 复制代码
public abstract class Buffer{
//JDK1.4时,引入的api
public final int capacity()//返回此缓冲区的容量
public final int position()//返回此缓冲区的位置
public final Buffer position(int newPositio)//设置此缓冲区的位置
public final int limit()//返回此缓冲区的限制
public final Buffer limit(int newLimit)//设置此缓冲区的限制
public final Buffer mark()//在此缓冲区的位置设置标记
public final Buffer reset()//将此缓冲区的位置重置为以前标记的位置
public final Buffer clear()//清除此缓冲区,即将各个标记恢复到初始状态,但是数据并没有真正擦除,
public final Buffer flip()//反转此缓冲区
public final Buffer rewind()//重绕此缓冲区
public final int remaining()//返回当前位置与限制之间的元素数
public final boolean hasRemaining()//告知在当前位置和限制之间是否有元素
public abstract boolean isReadOnly()://告知此缓冲区是否为只读缓冲区
//JDK1.6时引入的api
public abstract boolean hasArray();//告知此缓冲区是否具有可访问的底层实现数组
public abstract Object array();//返回此缓冲区的底层实现数组
public abstract int arrayOffset();/返回此缓冲区的底层实现数组中第一个缓冲区元素的偏移量
public abstract boolean is Direct();//告知此缓冲区是否为直接缓冲区
}

ByteBuffer

  1. 除了boolean,其他基本类型都有一个Buffer类型与之相对应,最常用的自然是 ByteBuffer 类(二进制数据),该类的主要方法如下:
java 复制代码
public abstract class ByteBuffer(
//缓冲区创建相关api
public static ByteBuffer allocateDirect(int capacity)//创建直接缓冲区
public static ByteBuffer allocate(int capacity)//设置缓冲区的初始容量
public static ByteBuffer wrap(byte[] array)//把一个数组放到缓冲区中使用
//构造初始化位置offset和上界length的缓冲区
public static ByteBuffer wrap(byte[] array,int offset, int length)
//缓存区存取相关API
public abstract byte get()//从当前位置position上get,get之后,position会自动+1 
public abstract byte get(int index);//从绝对位置get
public abstract ByteBuffer put(byte b);//从当前位置上添加,put之后,position会自动+1 
public abstract ByteBuffer put(int index,byte b);//从绝对位置上put

关于Buffer的注意事项和细节

  1. ByteBuffer支持类型化的put和get,数据类型必须保持一致,否则可能有 BufferUnderflowException 异常。
  2. Buffer支持转换为只读buffer,调用asReadOnlyBuffer()
  3. NIO还提供了MappedByteBuffer,可以让文件直接在内存(堆外内存) 中进行修改,而如何同步到文件由NIO来完成.
  4. NIO还支持通过多个Buffer(buffer数组)完成读写操作即 Scattering(分散)和 Gathering(合并)
相关推荐
救救孩子把7 分钟前
深入理解 Java 对象的内存布局
java
落落落sss10 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
万物皆字节15 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
夜雨翦春韭22 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
我行我素,向往自由28 分钟前
速成java记录(上)
java·速成
一直学习永不止步34 分钟前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
邵泽明35 分钟前
面试知识储备-多线程
java·面试·职场和发展
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
煸橙干儿~~1 小时前
分析JS Crash(进程崩溃)
java·前端·javascript
2401_854391081 小时前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端