Java NIO


总览

  • channel & buffer, buffer的数据能写入channel,同理channel的数据也可写入buffer中。

  • selectors。 单线程同时handle多个channel,借鉴Linux的IO多路复用。

    graph TB
    A[Thread] --> B{Selector}
    B -->C(Channel)
    B -->D(Channel)
    B -->E(Channel)
    C -->F(Buffer)
    F -->C
    D -->G(Buffer)
    G -->D
    

Buffer

一块可以先写入再读取的缓冲区,所有的Buffer都可读但不都可写,线程安全。以下表达式永远成立:mark(标记) <= position(位置) <= limit(界限) <= capacity(容量)。

基本用法

  1. 将数据写入Buffer;
  2. 调用buffer.flip(),切换到可读模式;
  3. 从buffer中读取数据;
  4. 调用buffer.clear() 清除整个缓冲区或者 buffer.compact()清除已经读取的区域
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {

  buf.flip();  //make buffer ready for read

  while(buf.hasRemaining()){
      System.out.print((char) buf.get()); // read 1 byte at a time
  }

  buf.clear(); //make buffer ready for writing
  bytesRead = inChannel.read(buf);
}
aFile.close();

Channel

NIO里面涉及的IO都从Channel开始。Channel有点像stream,但有如下不同:

  • 可以对一个channel读和写,Stream只能要么读要么写;
  • Channel支持异步读和写;
  • Channel总是将数据读到buffer中,或者从buffer中将数据写入channel。