在介绍NIO编程以前,咱们首先须要澄清一个概念:NIO究竟是什么的简称?有人称之为New I/O,由于它相对于以前的I/O类库是新增的,因此被称为New I/O,这是它的官方叫法。可是,因为以前老的I/O类库是阻塞I/O,New I/O类库的目标就是要让Java支持非阻塞I/O,因此,更多的人喜欢称之为非阻塞I/O(Non-block I/O),因为非阻塞I/O更可以体现NIO的特色,因此咱们这里使用NIO表示非阻塞I/O。编程
与Socket类和ServerSocket类相对应,NIO也提供了SocketChannel和ServerSocketChannel两种不一样的套接字通道实现。这两种新增的通道都支持阻塞和非阻塞两种模式。阻塞模式使用很是简单,可是性能和可靠性都很差,非阻塞模式则正好相反。开发人员通常能够根据本身的须要来选择合适的模式,通常来讲,低负载,低并发的应用程序能够选择同步阻塞I/O以下降编程复杂度,可是对于高负载,高并发的网络应用,须要使用NIO的非阻塞模式进行开发。数组
NIO类库简介网络
1. 缓冲区Buffer并发
咱们首先介绍缓冲区(Buffer)的概念,Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中,能够将数据直接写入或者将数据直接读到Stream对象中。高并发
在NIO库中,全部数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,写入到缓冲区中。任什么时候候访问NIO中的数据,都是经过缓冲区进行操做。性能
缓冲区实质上是一个数组。一般它是一个字节数组(ByteBuffer),也可使用其余种类的数组。可是一个缓冲区不只仅是一个数组,缓冲区提供了对数据的结构化访问以及维护读写位置(limit)等信息。spa
最经常使用的缓冲区是ByteBuffer,一个ByteBuffer提供了一组功能用于操做byte数组。除了ByteBuffer,还有其余的一些缓冲区,事实上,每一种Java基本类型(除了Boolean类型)都对应有一种缓冲区,具体以下:操作系统
ByteBuffer:字节缓冲区线程
CharBuffer:字符缓冲区对象
ShortBuffer:短整型缓冲区
IntBuffer:整型缓冲区
LongBuffer:长整型缓冲区
FloatBuffer:浮点型缓冲区
DoubleBuffer:双精度浮点型缓冲区
每个Buffer类都是Buffer接口的一个子实例。除了ByteBuffer,每个Buffer类都有彻底同样的操做,只是它们所处理的数据类型不同。由于大多数标准I/O操做都使用ByteBuffer,因此它除了具备通常缓冲区的操做以外还提供一些特有的操做,方便网络读写。
2. 通道Channel
Channel是一个通道,能够经过它读取和写入数据,它就像输水管道同样,网络数据经过Channel读取和写入。通道与流的不一样之处在于通道是双向的,流只是在一个方向上移动(一个流必须是InputStream 或者 OutputStream的子类),并且通道能够用于读,写或者同时用于读写。
由于Channel是全双工的,因此它能够比流更好地映射底层操做系统的API。特别是在UNIX网络编程模型中,底层操做系统的通道都是全双工的,同时支持读写操做。
根据Channel的类继承关系,实际上Channel能够分为两大类:分别是用于网络读写的SelectableChannel和用于文件操做的FileChannel。本节涉及的ServerSocketChannel和SocketChannel都是SelectableChannel的子类。
3. 多路复用器Selector
多路复用器Selector,它是Java NIO编程的基础,熟练地掌握Selector对于掌握NIO编程相当重要。多路复用器提供选择已经就绪的任务的能力。简单来说,Selector会不断地轮询注册在其上的Channel,若是某个Channel上面有新的TCP链接接入,读和写事件,这个Channel就处于就绪状态,会被Selector轮询出来,而后经过SelectionKey能够获取就绪Channel的集合,进行后续的I/O操做。
一个多路复用器Selector能够同时轮询多个Channel,因为JDK使用了epoll()代替传统的select实现,因此它并没有最大链接句柄1024/2048的限制。这也就意味着只须要一个线程负责Selector的轮询,就能够接入成千上万的客户端,这确实是个很是巨大的进步。