Java NIO

Java NIO

  • Java NIO:Non-blocking IO,非阻塞IO。例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情
  • Java NIO: Channels and Buffers,基于通道和缓冲区
  • Java IO是基于字节流和字符流操作;Java NIO是基于通道和缓存区,数据总是从通道读取到缓冲区,或者从缓存区写入到通道中
IONIO
面向流,单向面向缓冲区,双向
阻塞非阻塞
选择器
  • 面向流:直接是数据流动,数据单向流动;面向缓冲区:相当于管道,可双向

通道和缓冲区

  • 通道channel负责传输
  • 缓冲区buffer负责存储

缓冲区

  • 用于存储特定类型的数据
  • 除了boolean以外,其他类型都有对应的缓冲区,位于java.nio包
  • ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer
  • 通过allocate()静态方法方法获取缓冲区
  • 通过put()存数据,get()取数据
  • Buffer中重要的概念:capacity、limit限制、position位置、标记mark()、重置reset()
  • capacity容量:最大容量
  • limit限制:指向不能操作的第一个数据的索引
  • position:下一个要操作的数据的索引
  • 图中第一行是初始化状态
  • 图中第二行是写入状态,一直能写到最后,所以limit指向最后,即不能写的第一个区域
  • 图中第三行通过flip()方法,转为读取状态,当前可读取五个数据,limit指向不能读的第一个区域

  • 常用方法:

  • 获取数据:
  1. get():获取单个字节
  2. get(byte[] dst):读取多个字节到dst中
  3. get(int index):读取index索引位置的值,不会移动position
  • 存入数据:
  1. put(byte b):存入单个字节
  2. put(byte[] src):存入src
  3. put(int index, byte b):将字节写入指定索引,不会移动position

直接、非直接缓冲区

  • 非直接缓冲区:通过allocate()方法分配,建立在JVM内存中
  • 图中左边是OS直接内存,右边是JVM内存
  • 中间需要copy

  • 直接缓冲区:通过allocateDirect()方法分配,建立在OS物理内存中,读取时能够节省copy步骤
  • 物理内存文件直接建立在OS物理内存中,放进去之后虽然速度快,但是就JVM就不能操作了且成本较高

通道

  • 硬件有专门的channel通道用于读写,相当于专门处理读写的处理器,就不劳烦CPU了
  • Java中的通道,本身不存储数据,仅配合缓冲区完成数据传输,用于连接源节点和目标节点
  • 位于java.ino.channels.Channel接口:
  1. FileChannel:文件通道
  2. DatagramChannel:UDP读写通道
  3. SocketChannel:TCP读写通道
  4. ServerSocketChannel:服务器TCP读写通道,可以监听新来的TCP连接,新来一个连接就创建一个SocketChannel

分散和聚集

  • 分散读取指从Channel中读取的数据分散到多个Buffer中
  • 会按照缓冲垫额顺序来放

  • 聚集写入指将多个Buffer数据聚集到Channel中
  • 按照缓冲的顺序写入

阻塞与非阻塞

  • 传统的IO是阻塞的,当线程调用read/write时,该线程被阻塞,知道有数据被读取或写入,在此期间线程不能执行其他任务
  • NIO是非阻塞的,当线程从某通道进行读写数据时,没有数据可用的话,线程可以执行其他任务。所以单独的线程可以管理多个输入/输出通道,服务器可以使用一个或有限的线程来处理连接到服务器的所有客户端

选择器

  • 多路复用器,可以同时监控多个selectedChannel的IO状况,利用selector可以用一个线程管理多个Channel,通道要在selector上注册
  • selector是非阻塞IO的核心,结构如下图:

  • Selector支持三种,分别是SocketChannel、ServerSocketChnnel、DatagramChannel,三者用于网络通信。PipeChannel是用于线程、进程通信。FileChannel用于本地读取文件。
  • selector可以监听四种事件:
  1. 读:SelectionKey.OP_READ(1)
  2. 写:Selection.OP_WRITE(4)
  3. 连接:Selection.OP_CONNECT(8)
  4. 接收:Selection.OP_ACCEPT(16),当服务器监听来自新的客户端通道的TCP连接时,就是使用OP_ACCEPT
  • selector常用方法:

  • select()方法会一直阻塞直到有处理的IO请求

SelectionKey

  • 表示通道和选择器之间的注册关系
  • SelectionKey中存储,注册的是哪些监听事件、注册的通道和选择器,可以探测监听的事件是否准备好,准备好了就可以操作了

FileChannel

  • 是一个连接到文件的通道,只有阻塞模式
  • 无法直接打开一个FileChannel,需要通过使用一个InputStream、OutputStream或RandomAccessFile来获取一个FileChannel实例

SocketChannel

  • 是一个连接到TCP网络套接字的通道,有非阻塞模式,可以设置
  • 创建时要传入InetSocketAddress对象,里面含有IP和端口
  • 两种方式创建:
  1. 打开一个SocketChannel并连接到互联网上的某台服务器(客户端)
  2. 一个新连接到达ServerSocketChannel时,会创建一个SocketChannel(服务器)

ServerSocketChannel

  • 是一个可以监听新进来的TCP连接的通道,用于服务端,有非阻塞模式,可以设置
  • 创建时要传入InetSocketAddress对象,里面含有端口

DatagramChannel

  • 是一个能收发UDP包的通道,UDP是无连接的网络协议,所以不能像其它通道那样读取和写入,有非阻塞模式,可以设置
  • 创建时要传入InetSocketAddress对象,里面含有IP和端口(服务器端仅有端口)
  • 由于UDP是无连接的,连接到特定地址并不会像TCP通道那样创建一个真正的连接

Pipe

  • 管道是2个线程之间的单向数据连接
  • Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。数据是单向流动的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值