NIO简介
Java NIO(New IO)是Java提供的一种基于通道(Channel)和缓冲区(Buffer)的IO方式,与传统的IO(基于字节流和字符流)相比,NIO能够更高效地处理IO操作。Java NIO最具有代表性的组件是ByteBuffer,它是一个字节缓冲区,可以读取和写入数据。除了ByteBuffer之外,Java NIO还提供了CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer等缓冲区实现,以及FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel等通道实现。
NIO实现模型
通过JDK的源码可以看出,Java语言的NIO(New IO)组件,在Linux系统上,是使用的是select系统调用实现的。所以,Java语言的NIO(New IO)组件所使用的,就是IO多路复 用模型。
NIO怎么实现非阻塞?
Java NIO中的非阻塞IO是通过选择器(Selector)实现的。Selector允许单个线程处理多个通道的IO操作。在非阻塞模式下,一个线程可以管理多个通道,从而提高了IO的效率。当一个通道准备好进行读写操作时,它就会被选择器选中,并返回相应的键(SelectionKey),然后再通过相应的键来进行后续的IO操作。
好的,这样我们把基础概念搞清楚以后再开始来整体了解NIO。
NIO与OIO区别
JavaNIO为非阻塞IO(Non-Block IO),OIO(Old IO)为“老的”阻塞式Java IO。
Java NIO是一种基于通道和缓冲区的IO方式,相比传统的IO更高效。NIO的非阻塞IO是通过选择器实现的,允许单个线程处理多个通道的IO操作,从而提高了IO的效率。与OIO相比,NIO是面向缓冲区的,不是顺序操作,可以随意读取和修改Buffer中任意位置的数据。OIO的操作是阻塞的,而NIO的操作是非阻塞的。NIO中引入了Channel和Buffer的概念,用户程序只需要从通道中读取数据到缓冲区中,或将数据从缓冲区中写入到通道中。
Java NIO类库包含以下三个核心组件:
Channel(通道)
Buffer(缓冲区)
Selector(选择器)
让我们来分别介绍一下
通道(Channel)
在NIO中,网络连接使用通道(Channel)表示,所有的NIO IO操作都是通过通道完成的。通道类似于OIO中的两个流的结合体,既可从通道读取数据,也可向通道写入数据。
Channel和Stream的区别:
Stream是单向的,譬如InputStream是单向的只读流,OutputStream是单向的只写流;
而Channel是双向的,既可以用来进行读操作,又可以用来进行写操作。
NIO中的Channel的主要实现有:
FileChannel 用于文件IO操作
DatagramChannel 用于UDP的IO操作
SocketChannel 用于TCP的传输操作
ServerSocketChannel 用于TCP连接监听操作
选择器(Selector)
什么是IO多路复用?
IO多路复用是指一个进程/线程可以同时监视多个文件描述符(包括socket连接),并且只需要使用一个线程就能够管理多个通道的IO操作。
那么在Java应用层面,要实现对多个文件描述符的监视,就需要使用Java NIO组件中的Selector选择器。Selector选择器可以看作是一个IO事件的监听器和查询器,通过它,一个线程可以查询多个通道的IO事件是否就绪。一旦选择器确定某个通道上有可读或可写的数据时,就会返回相应的键(SelectionKey),用户程序可以通过键来进行后续的IO操作。
那么IO事件又是什么?
在Java NIO中,IO事件是指一些特定的操作,如数据可读、数据可写等。
Java NIO只定义了四个事件,用SelectionKey的四个常量来表示:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
Selector选择器可以监听多个通道上的IO事件,一旦某个通道上的IO事件就绪,就会返回相应的键(SelectionKey),用户程序可以通过键来进行后续的IO操作。
IO多路复用流程
1.需要把通道注册到选择器中
2.通过选择器所提供的事件查询(select)方法,查询注册的通道是否有已经就绪的IO事 件(例如可读、可写、网络连接完成等)。
由于一个选择器只需要一个线程进行监控,所以就可以很简单地使用一个线程,通过选择器去管理多个连接通道。
Java NIO使用选择器的最大优势在于可以大大减小系统开销,因为系统不必为每一个网络连接(文件描述符)创建进程/线程。这种高效的处理方式可以达到一个线程负责多个连接通道的IO处理,从而提高了系统的性能。Java NIO的高效,正是来自于其选择器组件Selector和底层操作系统IO多路复用技术的支持。
缓冲区(Buffer)
在 NIO 中,应用程序与通道(Channel)之间的交互主要涉及数据的读取和写入。为了实现 NIO 的非阻塞读写操作,NIO 提供了一个重要的组件——NIO 缓冲区(NIO Buffer)。缓冲区是一个容器,实际上是一个连续的数组。通道提供了从文件或网络读取数据的渠道,但是读写的数据都必须经过缓冲区。
在NIO中,数据的读取和写入必须经过缓冲区。通道(Channel)提供了从文件或网络读取数据的渠道,而缓冲区(Buffer)则是一个容器,实际上是一个连续的数组。所谓通道的读取,就是将数据从通道读取到缓冲区中;所谓通道的写入,就是将数据从缓冲区中写入到通道中。缓冲区的使用是面向流进行读写操作的OIO所没有的,也是NIO非阻塞的重要前提和基础之一。
java nio的简单介绍就到这里,后面详细阐述三大组件。