Java中的NIO

NIO的几个概念

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

1. 通道

顾名思义,就是通向什么的道路,为某个提供了渠道。在传统IO中,我们要读取一个文件中的内容,通常是像下面这样读取的:

public class Test {
    public static void main(String[] args) throws IOException  {
        File file = new File("data.txt");
        InputStream inputStream = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        inputStream.read(bytes);
        inputStream.close();
    }  
}

这里的InputStream实际上就是为读取文件提供一个通道的。

因此可以将NIO 中的Channel同传统IO中的Stream来类比,但是要注意,传统IO中,Stream单向的,比如InputStream只能进行读取操作,OutputStream只能进行写操作。而Channel双向的,既可用来进行读操作,又可用来进行写操作。

2. Buffer(缓冲区)

在NIO中所有数据的读和写都离不开Buffer。比如上面的一段代码中,读取的数据时放在byte数组当中,而在NIO中,读取的数据只能放在Buffer中。同样地,写入数据也是先写入到Buffer中。

3. Selector

Selector的作用就是用来轮询每个注册的Channel,一旦发现Channel有注册的事件发生,便获取事件然后进行处理。


用单线程处理一个Selector,然后通过Selector.select()方法来获取到达事件,在获取了到达事件之后,就可以逐个地对这些事件进行响应处理。

Channel

Channel和传统IO中的Stream很相似。虽然很相似,但是有很大的区别,主要区别为:通道是双向的,通过一个Channel既可以进行读,也可以进行写;而Stream只能进行单向操作,通过一个Stream只能进行读或者写;

以下是常用的几种通道:

  • FileChannel : 可以从文件读或者向文件写入数据
  • SocketChanel: 以TCP来向网络连接的两端读写数据
  • ServerSocketChannel:监听客户端发起的TCP连接,并为每个TCP连接创建一个新的SocketChannel来进行数据读写
  • DatagramChannel:以UDP协议来向网络连接的两端读写数据

下面给出通过FileChannel来向文件中写入数据的一个例子:

public class Test {
    public static void main(String[] args) throws IOException  {
        File file = new File("data.txt");
        FileOutputStream outputStream = new FileOutputStream(file);
        FileChannel channel = outputStream.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        String string = "java nio";
        buffer.put(string.getBytes());
        buffer.flip();     //此处必须要调用buffer的flip方法
        channel.write(buffer);
        channel.close();
        outputStream.close();
    }  
}

Buffer

实际上是一个容器,是一个连续数组。Channel提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由Buffer。具体看下面这张图就理解了:

客户端发送数据时,必须先将数据存入Buffer中,然后将Buffer中的内容写入通道。服务端这边接收数据必须通过Channel将数据读入到Buffer中,然后再从Buffer中取出数据来处理。

在NIO中,Buffer是一个顶层父类,它是一个抽象类,常用的Buffer的子类有:

  • ByteBuffer
  • IntBuffer
  • CharBuffer
  • LongBuffer
  • DoubleBuffer
  • FloatBuffer
  • ShortBuffer

Selector

Selector能够检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。只是用一个单线程就可以管理多个通道,也就是管理多个连接。只有在连接真正有读写事件发生时,才会调用函数来进行读写,就大大地减少了系统开销。

参考
海子:Java NIO概述

你可能感兴趣的:(Java中的NIO)