Java I/O模型

Posted 林夕Emma

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java I/O模型相关的知识,希望对你有一定的参考价值。

本文转发自技术世界原文链接 http://www.jasongj.com/java/nio_reactor/

 

同步 vs. 异步

同步I/O 

每个请求必须逐个地被处理,一个请求的处理会导致整个流程的暂时等待,

这些事件无法并发地执行。用户线程发起I/O请求后需要等待或者轮询内核I/O操作完成后才能继续执行。

同步意味着一个任务的某个处理过程会对多个线程在用串行化处理

异步I/O 

多个请求可以并发地执行,一个请求或者任务的执行不会导致整个流程的暂时等待。

用户线程发起I/O请求后仍然继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

异步则意味着某个处理过程可以允许多个线程同时处理。


 

阻塞 vs. 非阻塞

阻塞 

某个请求发出后,由于该请求操作需要的条件不满足,请求操作一直阻塞,不会返回,直到条件满足。

非阻塞 

请求发出后,若该请求需要的条件不满足,则立即返回一个标志信息告知条件不满足,而不会一直等待。

一般需要通过循环判断请求条件是否满足来获取请求结果。

需要注意的是,阻塞并不等价于同步,而非阻塞并非等价于异步。

事实上这两组概念描述的是I/O模型中的两个不同维度。

同步和异步着重点在于多个任务执行过程中,后发起的任务是否必须等先发起的任务完成之后再进行。

而不管先发起的任务请求是阻塞等待完成,还是立即返回通过循环等待请求成功。

阻塞和非阻塞重点在于请求的方法是否立即返回(或者说是否在条件不满足时被阻塞)


 

Java中四种I/O模型

Java最早提供的blocking I/O即是阻塞I/O,


如上文所述,阻塞I/O下请求无法立即完成,则保持阻塞。


阻塞I/O分为如下两个阶段:
阶段1:等待数据就绪。网络 I
/O 的情况就是等待远端数据陆续抵达;磁盘I/O的情况就是等待磁盘数据从磁盘上读取到内核态内存中。
阶段2:数据拷贝。出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中。

 

而NIO即是非阻塞I/O

非阻塞I/O请求包含如下三个阶段

1)socket设置为 NONBLOCK(非阻塞)就是告诉内核,

  当所请求的I
/O操作无法完成时,不要将线程睡眠,而是返回一个错误码(EWOULDBLOCK) ,这样请求就不会阻塞。
2)I
/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。

  整个I/O 请求的过程中,虽然用户线程每次发起I/O请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的 CPU 的资源。
3)数据准备好了,从内核拷贝到用户空间。

一般很少直接使用这种模型,而是在其他I
/O模型中使用非阻塞I/O 这一特性。这种方式对单个I/O 请求意义不大,但给I/O多路复用提供了条件。

 

同时通过NIO实现的Reactor模式即是 I/O复用模型的实现,

I/O多路复用(异步阻塞 I/O)
I
/O多路复用会用到select或者poll函数,这两个函数也会使线程阻塞,


但是和阻塞I/O所不同的是,这两个函数可以同时阻塞多个I/O操作。

而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。 从流程上来看,使用select函数进行I/O请求和同步阻塞模型没有太大的区别,甚至还多了添加监视Channel,以及调用select函数的额外操作,增加了额外工作。

但是,使用 select以后最大的优势用户可以在一个线程内同时处理多个Channel的I/O请求。

用户可以注册多个Channel,然后不断地调用select读取被激活的Channel,即可达到在同一个线程内同时处理多个I/O请求的目的。

而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。 调用select
/poll该方法由一个用户态线程负责轮询多个Channel,直到某个阶段1的数据就绪,再通知实际的用户线程执行阶段2的拷贝。


通过一个专职的用户态线程执行非阻塞I/O轮询,模拟实现了阶段一的异步化。

 

通过AIO实现的Proactor模式即是异步I/O模型的实现

调用AIO_read 函数,告诉内核描述字,缓冲区指针,缓冲区大小,文件偏移以及通知的方式,然后立即返回。

当内核将数据拷贝到缓冲区后,再通知应用程序。所以异步I/O模式下,阶段1和阶段2全部由内核完成,完成不需要用户线程的参与。

 





























以上是关于Java I/O模型的主要内容,如果未能解决你的问题,请参考以下文章

Unix I/O与Java I/O

Unix I/O与Java I/O

Unix I/O与Java I/O

Java基础:I/O多路复用模型及Linux中的应用

Java IO模型详解

Java I/O模型