NIO

Author Avatar
丁起男 09月 08,2020
  • 在其它设备中阅读本文章

NIO

bio的面向流的io,它建立的通道都是单向的,所以输入和输出流的通道不相同,必须建立2个通道,通道内都是传输的字节数组

nio中,不再是面向流的io了,而是面向缓冲区,它会建立一个通道(Channel),而通道上会有一个缓冲区(Buffer)用于存储真正的数据

通道只是作为运输数据的一个连接资源,而真正存储数据的是缓冲区。即通道负责传输,缓冲区负责存储

BIONIO
面向流(Stream)面向缓冲区(Buffer)
单向通道双向通道
阻塞IO非阻塞IO
选择器(Selectors)

缓冲区(Buffer)

缓冲区是存储数据的区域,在java中,缓冲区就是数组,为了可以操作不同数据类型的数据,java提供了许多不同类型的缓冲区,除了布尔类型以外,其它基本类型都用对应的缓冲区数组对象

为什么没有布尔类型的缓冲区?

在java中,boolean类型数据只占用1bit,而在io传输过程中,都是以字节为单位进行传输的,所以boolean的1bit完全可以使用byte类型的某一位,或者int类型的某一位表示,没必要为了这1bit而专门提供一个缓冲区

缓冲区存储类型
ByteBuffer字节
CharBuffer字符
ShortBuffer短整型
IntBuffer整形
LongBuffer长整型
FloatBuffer单精度浮点型
DoubleBuffer双精度浮点型

分配一个缓冲区

  • allocate()

读写数据

  • put():将数据写入到缓冲区中
  • get():从缓冲区读取数据

重要属性

  • capacity:缓冲区中最大存储数据的容量,一旦声明则无法改变
  • limit:表示缓冲区可以操作数据的大小,limit之后的数据无法进行读写。必须满足limit<=capacity
  • position:当前缓冲区正在操作数据的下标位置,必须满足position<=limit
  • mark:标记位置,调用reset()将position位置调整到mark属性指向的下标位置,实现多次读取数据

辅助方法

  • flip():可以实现读写模式切换,会将limit设置为当前写的位置,position设置为0,即从头开始读取
  • rewind():可以将position位置设置为0,再次读取缓冲区中的数据
  • clear():情况整个缓冲区,它会将position设置为0,limit设置为capacity,可以写整个缓冲区

通道(Channel)

通道作为一种连接资源,作用是传输数据,而真正存储数据的是缓冲区

通道是可以双向读写的,传统bio需要使用输入\输出流表示数据的流向,zainio中可以减少通道资源的消耗

通道类

io通道类型具体类
文件ioFileChannel(用于文件读写)
tcp网络ioSocketChannel(用于读写数据的tcp通道)
ServerSocketChannel(监听客户端的连接)
udp网络ioDatagramChannel(收发udp数据报的通道)

获取通道

可以通过getChannel()方法获取一个通道

  • 文件io:FileInputStream、FileOutputStream、RandomAccessFile
  • tcp网络:Socket、ServerSocket
  • udp网络:DatagramSocket

选择器(Selectors)

底层利用了多路复用io机制,让选择器可以监听多个io连接,根据io的状态响应到服务器端进行处理

选择器可以连接监听多个io连接,而传统的bio每个io连接都需要有一个线程去监听和处理

在java nio中,选择器使用Selector类表示,Selector可以接收各种io连接,在io状态准备就绪时,会通通知通道注册的Selector,Selector在下一次轮询时会发现该io连接就绪,进而处理该连接

基本结构

重要方法方法解析
open()打开一个Selector选择器
select()阻塞的等待就绪的通道
select(long timeout)最多阻塞timeout毫秒,如果是0则一直阻塞等待
selectNow()非阻塞的轮询就绪的通道

如果用户进程轮询时没有发现就绪的通道

  • 一直等待直到一个就绪的通道,再返回给用户进程
  • 立刻返回一个错误状态码给用户进程,让用户进程继续运行,不会阻塞

选择键

在选择器轮询到就绪通道时会返回这些通道的就绪选择键,通过选择键可以获取到通道进行操作

  • SelectionKey.OP_READ:套接字通道准备好进行读操作
  • SelectionKey.OP_WRITE:套接字通道准备好进行写操作
  • SelectionKey.OP_ACCEPT:服务器套接字通道接收其它通道
  • SelectionKey.OP_CONNECT:套接字通道准备完成连接

SelectionKey的属性

  • channel:该选择键绑定的通道
  • selector:轮询到该选择键的选择器
  • readyOps:当前就绪选择键的值
  • InteresOps:该选择器对该通道感兴趣的所有选择器

原文章地址:
http://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650779621&idx=2&sn=84f025c04554191b1f00b9d37129146f&chksm=bea7de3689d057207703533a2e9a8bcd752e97450c6048f3d931dc1158bd073578affedfacfe&mpshare=1&scene=24&srcid=0907wxaRmQ2lABmaYF7aweFm&sharer_sharetime=1599475054812&sharer_shareid=0c953d57735530819d113507100ae2b3#rd