Java IO学习笔记(一):BIO,NIO,AIO基础概念

什么是I/O

我一般了解一个专业术语,会先从她的英文意思开始了解,在计算机系统中I/O就是输入(Input)和输出(Output)的意思,针对不同的操作对象,可以划分为磁盘I/O模型,网络I/O模型,内存I/O等,只要具有输入输出类型的交互系统都可以认为是I/O系统,也可以说I/O是整个操作系统数据交换与人机交互的通道,这个概念与选用的开发语言没有关系,是一个通用的概念。

在如今的系统中I/O却拥有很重要的位置,现在系统都有可能处理大量文件,大量数据库操作,而这些操作都依赖于系统的I/O性能,也就造成了现在系统的瓶颈往往都是由于I/O性能造成的。

IO NIO
面向流 面向缓冲
阻塞IO 非阻塞IO
选择器

这里先给出BIO、NIO、AIO的类比描述:

  • BIO (Blocking I/O):同步阻塞
  • NIO (New I/O):同步非阻塞
  • AIO ( Asynchronous I/O):异步非阻塞I/O模型

什么是阻塞、非阻塞,同步、异步?

阻塞,非阻塞。侧重点是调用者。阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞:调用者一直等待结果。非阻塞:调用者可以做其他事情,但还是要自己每隔一段时间检查返回结果。

同步,异步。侧重点是被调用者。同步:被调用者不会主动通知调用者结果,需要调用者主动等待结果,等待期间不能做任何事情。异步:被调用者会主动通知调用者结果,调用者不必等待。

举个例子,我去书店买书,问老板有没有我需要的书

  • 调用者:我
  • 被调用者:老板

再说一遍:阻塞、非阻塞对象是【调用者】(本例中的【我】),同步、异步的对象是【被调用者】(本例中的【老板】)。

1、同步阻塞

我去买书,我问老板有没有书,老板去找,在这期间我一直等待,并主动询问老板有没有找到。

2、同步非阻塞

老板找书的过程中,我可以做其他事,但是还是要自己周期性问老板有没有找到。

3、异步阻塞

我还是站在那里等,这里如果找到书,老板会主动通知我。(这种情况没有意义)

4、异步非阻塞

老板找书过程中,我可以去做其他事情,不用自己回来问,老板会自己通知我。

面向流与面向缓冲?

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

Java NIO

Java NIO 由以下几个核心部分组成:

  • Channels
  • Buffers
  • Selectors

缓冲区 Buffer

    Buffer是一个对象,包含一些要写入或者读出的数据。
    在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
    缓冲区实际上是一个数组,并提供了对数据结构化访问以及维护读写位置等信息。

    具体的缓存区有这些:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。

以下是Java NIO里关键的Buffer实现:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。

通道 Channel

    我们对数据的读取和写入要通过Channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。
    底层的操作系统的通道一般都是全双工的,所以全双工的Channel比流能更好的映射底层操作系统的API。
    Channel主要分两大类:
    SelectableChannel:用户网络读写
    FileChannel:用于文件操作

    后面代码会涉及的ServerSocketChannel和SocketChannel都是SelectableChannel的子类。

下面是JAVA NIO中的一些主要Channel的实现:

  • FileChannel 从文件中读写数据。
  • DatagramChannel 能通过UDP读写网络中的数据。
  • SocketChannel 能通过TCP读写网络中的数据。
  • ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。

Channel与Buffer关系

Channel读写数据要通过Buffer

Java IO学习笔记(一):BIO,NIO,AIO基础概念

多路复用器 Selector

    Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。
这是在一个单线程中使用一个Selector处理3个Channel的图示:
Java IO学习笔记(一):BIO,NIO,AIO基础概念
要使用Selector,要向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

参考:

http://www.importnew.com/19046.html

https://blog.csdn.net/anxpp/article/details/51512200