johnnian/Blog

Java基础—NIO基础概念

Opened this issue · 0 comments

一、I/O & NIO

Java的IO流,根据类型不同划分为(具体继承这些IO类的子类非常多)

  • 基于字节操作的 I/O 接口:InputStreamOutputStream
  • 基于字符操作的 I/O 接口:WriterReader
  • 基于磁盘操作的 I/O 接口:File
  • 基于网络操作的 I/O 接口:Socket

Java传统的IO类操作都是阻塞的,在高并发的场景下性能令人堪忧。

Java NIO(Non-blocking IO)是JDK1.4之后推出的一套新IO接口——非阻塞IO,与传统IO接口的主要区别在于:

I/O NIO
线程阻塞 线程非阻塞
用流(Stream)的方式处理数据 用缓冲区(Buffer)的方式处理数据

二、NIO基本概念

  • Channel(通道)
  • Buffer(缓冲区)
  • Selector(选择器)

2.1 Channel

1). Channel,相对于Stream,有几点区别:

Channel Stream
双向(可以读写) 单向(只能读或只能写)
非阻塞操作 阻塞操作
基于Buffer 基于流

2). NIO数据的流向总是:

Channel ----> Buffer
Channel <---- Buffer

3). Channel主要有下面几种类型:

类型 说明
FileChannel 文件的数据读写
DatagramChannel UDP的数据读写
SocketChannel TCP的数据读写
ServerSocketChannel 监听TCP链接请求,并且创建SocketChannel

4). 具体获取Channel的类

类型 说明
FileChannel FileInputStream.getChannel()
FileOutputStream.getChannel()
RandomAccessFile.getChannel()
DatagramChannel DatagramChannel.open()
SocketChannel SocketChannel.open()
ServerSocketChannel ServerSocketChannel.open()

2.2 Buffer

Buffer实际上就是一块内存区,用于和Channel交互,需要注意的是:

Buffer是非线程安全的,如果需要在多线程环境中使用,则需要有同步锁。

1). Buffer基本概念

要真正理解Buffer,有一张图比较经典:

  • capacity: buffer的容量大小,一般在创建之后就不会再改变;
  • limit: buffer内存区中还未被读写的第一个element位置索引;
  • position: 下一个等待要被读写的element位置索引;
  • mark: 当调用reset方法时,position会被重置的位置索引;

通常,0 <= mark <= position <= limit <= capacity

buffers-modes

2). Buffer类型

Buffer名字 对应基础类型
ByteBuffer byte
CharBuffer char
DoubleBuffer double
FloatBuffer float
IntBuffer int
LongBuffer long

3). Buffer常用操作

buffer操作 具体
clear() limit=capacity, position=0, mark忽略
flip() limit= position, position=0, mark忽略
rewind() position=0, mark忽略
compact()
(ByteBuffer才有)
将整块Buffer(从position~limit)移动到Buffer开始的位置(0~limit-position)

Buffer常用操作模式:

  • 把数据写入buffer;
  • 调用flip;
  • 从buffer中读取数据;
  • 调用buffer.clear()清空整个buffer 或者 buffer.compact()清空已经读取的buffer

2.3 Selector

Selector是NIO中的组件,检查一个或多个channel,实现一个线程管理多个网络链接。

overview-selectors

使用步骤:

  • 创建 selector
  • 注册channel到selector

Channel必须是非阻塞的。所以FileChannel不适用Selector,因为FileChannel不能切换为非阻塞模式。Socket channel可以正常使用。

参考链接