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
通道 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
多路复用器 Selector
Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。这是在一个单线程中使用一个Selector处理3个Channel的图示:
要使用Selector,要向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
参考:
http://www.importnew.com/19046.html
https://blog.csdn.net/anxpp/article/details/51512200