Skip to content

Latest commit

 

History

History
54 lines (35 loc) · 4.14 KB

2.1-XNIO基础.md

File metadata and controls

54 lines (35 loc) · 4.14 KB

XNIO基础

Undertow的NIO使用XNIO组件,这一篇介绍什么是NIO,以及XNIO的基础。

NIO

Java NIO 是由 Java 1.4 引进的异步 IO,Java NIO 由以下几个核心部分组成:

  • Channel
  • Buffer
  • Selector

NIO 和 IO 的对比

IO 和 NIO 的区别主要体现在三个方面:

  • IO 基于流(Stream oriented), 而 NIO 基于 Buffer (Buffer oriented)
  • IO 操作是阻塞的, 而 NIO 操作是非阻塞的
  • IO 没有 selector 概念, 而 NIO 有 selector 概念
  1. 基于 Stream 与基于 Buffer

传统的 IO 是面向字节流或字符流的,而在 NIO 中,我们抛弃了传统的 IO 流,而是引入了 ChannelBuffer 的概念。在 NIO 中,我只能从 Channel 中读取数据到 Buffer 中或将数据从 Buffer 中写入到 Channel。

那么什么是 基于流 呢? 在一般的 Java IO 操作中,我们以流式的方式顺序地从一个 Stream 中读取一个或多个字节,因此我们也就不能随意改变读取指针的位置。

基于 Buffer 就显得有点不同了,我们首先需要从 Channel 中读取数据到 Buffer 中,当 Buffer 中有数据后,我们就可以对这些数据进行操作了,不像 IO 那样是顺序操作,NIO 中我们可以随意地读取任意位置的数据。

  1. 阻塞和非阻塞

Java 提供的各种 Stream 操作都是阻塞的, 例如我们调用一个 read 方法读取一个文件的内容, 那么调用 read 的线程会被阻塞住, 直到 read 操作完成。

而 NIO 的非阻塞模式允许我们非阻塞地进行 IO 操作。例如我们需要从网络中读取数据,在 NIO 的非阻塞模式中,当我们调用 read 方法时,如果此时有数据,则 read 读取并返回,如果此时没有数据,则 read 直接返回,而不会阻塞当前线程。

  1. selector

selector 是 NIO 中才有的概念, 它是 Java NIO 之所以可以非阻塞地进行 IO 操作的关键。

通过 Selector, 一个线程可以监听多个 Channel 的 IO 事件, 当我们向一个 Selector 中注册了 Channel 后, Selector 内部的机制就可以自动地为我们不断地查询(select) 这些注册的 Channel 是否有已就绪的 IO 事件(例如可读, 可写, 网络连接完成等)。通过这样的 Selector 机制,我们就可以很简单地使用一个线程高效地管理多个 Channel 了。

XNIO

XNIO基于JDK NIO扩展和封装,提供一套包含阻塞和非阻塞IO的简单API,不用麻烦的操作Selector,XNIO有下面特点:

  • Channel,是传输管道的抽象概念,在NIO的Channel上进行的扩展加强,使用ChannelListener API进行事件通知。在创建Channel时,就赋予IO线程,用于执行所有的ChannelListener回调方法。
  • 区分IO线程和工作线程,创建一个工作线程池可以用来执行阻塞任务。一般情况下,非阻塞的Handler由IO线程执行,而阻塞任务比如Servlet则被调度到工作线程池执行。这样就很好的区分了阻塞和非阻塞的两种情形。
  • 对ByteBuffer进行池化管理。简单来说就是开发者在程序开始时就计划好读写缓存区大小,统一分配好放到池中,Xnio中有Pool和Pooled接口用来管理池化缓存区。以前在接收网络数据时,往往简单的new出一块数据区,填充,解析,使用,最后丢弃,这种方法随着大量的数据读入,必然造成GC反复出现。重用缓存区就可以在这个方面解决一部分问题。

为什么使用XNIO

业界主要流行的NIO框架有NettyMina,关于Undertow为什么使用XNIO,官方的答复如下:

简单来说,就是XNIO跟Undertow都是JBoss下面的产品,并且XNIO提供的功能刚好跟Undertow要求的契合,还有XNIO有更好的向后兼容能力,这点对Undertow是很重要的概念,所以选择XNIO作为Undertow底层的NIO实现框架。

资料