以nio怎么读为中心

发布时间:2023-05-20

一、NIO的概念

Java NIO(New IO)是一个在JDK1.4中推出的新IO API。它以更接近操作系统底层的方式进行文件操作,相对于传统的IO流,在性能和灵活性方面都有很大的提升。Java NIO主要由以下几个核心部分构成:

  • Channels: 通道
  • Buffers: 缓冲区
  • Selectors: 选择器 通道和缓冲区是NIO数据的核心,选择器则是一个可以用来监视多个通道的对象,是否有事件(如新连接、数据接收)发生。这种方式比旧的阻塞式I/O处理方式更为高效。

二、Channel

Channel,通道是NIO中的一个基本概念。它指的是可以进行IO操作的对象,如文件或网络连接。Channel与传统IO中的流(Stream)有一些重要的区别:

  • 可以既读又写(流必须分别进行读写)
  • 可以异步地进行读写
  • 从Channel中读取的数据总是被读到Buffer中,从Buffer写入到Channel中的数据也总是被写入到Channel中 下面的代码段说明了如何创建一个文件通道并读取其中的内容:
try {
   RandomAccessFile aFile = new RandomAccessFile("file.txt", "rw");
   FileChannel inChannel = aFile.getChannel();
   ByteBuffer buffer = ByteBuffer.allocate(48);
   int bytesRead = inChannel.read(buffer);
   while (bytesRead != -1) {
       System.out.println("Read " + bytesRead);
       buffer.flip();
       while(buffer.hasRemaining()){
           System.out.print((char) buffer.get());
       }
       buffer.clear();
       bytesRead = inChannel.read(buffer);
   }
   aFile.close();
} catch (IOException e) {
   e.printStackTrace();
}

三、Buffer

Buffer是一个用于存储数据的内存块。在NIO库中,所有数据都是用缓冲区处理的。缓冲区实质上是一个数组,并提供了一组方法,方便对数据的存储和检索。 下面的代码段说明了如何创建一个缓冲区并使用put()方法将数据写入缓冲区,并使用flip()方法将Buffer从写模式切换到读模式:

ByteBuffer buf = ByteBuffer.allocate(48);
buf.put("hello world".getBytes());
buf.flip();
while(buf.hasRemaining()){
    System.out.print((char) buf.get());
}

四、Selector

Selector是SelectableChannel对象的多路复用器,用于检查一个或多个通道是否处于准备好状态(如读就绪、写就绪)。 下面的代码段说明了如何使用Selector的代码:

Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
while(true) {
    int readyChannels = selector.select();
    if(readyChannels == 0) continue;
    Set<SelectionKey> selectedKeys = selector.selectedKeys();
    Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
    while(keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();
        if(key.isAcceptable()) {
            // a connection was accepted by a ServerSocketChannel.
        } else if (key.isConnectable()) {
            // a connection was established with a remote server.
        } else if (key.isReadable()) {
            // a channel is ready for reading
        } else if (key.isWritable()) {
            // a channel is ready for writing
        }
        keyIterator.remove();
    }
}

五、总结

通过对NIO三个核心部分(通道、缓冲区、选择器)的介绍和示例代码的讲解,可以明确NIO相对于传统IO在性能和灵活性方面的提升。对于Java开发人员,掌握NIO的基础知识,并深入理解其使用方式,将大幅提升开发效率和性能。