NIO(New IO)是从Java1.4开始引入的,是可以替代Java IO API 的API。与阻塞式IO(传统IO)不同,他提出了非阻塞信道和事件驱动的IO编程模式。现在常见的技术框架,很多都采用了NIO技术,例如:Tomcat、Netty、Jetty等。所以,学习和掌握NIO技术已经是程序员们必备的技能。

     Java.nio包中包含了很多类和组件,提供了很多高级的特性。其中核心应属:Channels、Buffer、Selector这三部分。Channel和Buffer有好几种类型,channel的主要实现包括有:FileChannel、DatagramChannel、SocketChannel与ServerSocketChannel,涵盖了TCP、UDP的网络IO以及文件IO。关于Buffer的实现基本是java基本类型的缓冲实现,即:ByteBuffer、CharBuffer、DoubleBuffer、IntBuffer、FloatBuffer、ShortBuffer、LongBuffer。其中,还有个MappedByteBuffer,用于表示内存映射文件,大大提高了文件的读写效率。Selector允许单线程处理多个Channel通道,如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便,例如在一个聊天服务器中。下图是一个单线程使用一个Selector处理三个channel的示图:

java如何将buffer写成文件 java io buffer_非阻塞


要使用Selector,必须向Selector中注册Channel,然后调用他的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪,一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

       NIO与传统IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。JAVA IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读区的数据,需要先将它缓存到一个缓冲区。NIO的缓冲导向方法略有不同。数据读取到它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这一特性增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

       IO的各种流是阻塞的。这意味着,当一个线程调用read()或write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以做其他的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待他完全写入,这个线程可以同时去做别的事情。线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出的通道。

       总之,NIO的读写都是操作缓冲区(Buffer)的,然后通过通道(channel )进行数据的交互。这篇文章先大概总结下NIO的特性及基本概念,后面详细贴出其具体的实现机制与实例。NIO中除了这三个核心部分外,还有Pipe、FileLock、Scatter(分散)/Gatter(聚集)、transferFrom/transferTo等,后面博文再一一详细介绍。