JAVA 中BIO,NIO,AIO的区别

来源:互联网 发布:棉柔巾 知乎 编辑:程序博客网 时间:2024/05/29 03:40

原文:http://bbym010.iteye.com/blog/2100868


同步阻塞IO(JAVA BIO): 
    同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 

同步非阻塞IO(Java NIO) : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问。 

异步阻塞IO(Java NIO):  
   此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄(如果从UNP的角度看,select属于同步操作。因为select之后,进程还需要读写数据),从而提高系统的并发性!  


(Java AIO(NIO.2))异步非阻塞IO:  
   在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。    



BIO、NIO、AIO适用场景分析: 

    BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。 

    NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。 

    AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。 

搞清楚了以上概念以后,我们再回过头来看看,Reactor模式和Proactor模式。  
  
(其实阻塞与非阻塞都可以理解为同步范畴下才有的概念,对于异步,就不会再去分阻塞非阻塞。对于用户进程,接到异步通知后,就直接操作进程用户态空间里的数据好了。)  
  
首先来看看Reactor模式,Reactor模式应用于同步I/O的场景。我们分别以读操作和写操作为例来看看Reactor中的具体步骤:  
读取操作:  
1. 应用程序注册读就绪事件和相关联的事件处理器  
  
2. 事件分离器等待事件的发生  
  
3. 当发生读就绪事件的时候,事件分离器调用第一步注册的事件处理器  
  
4. 事件处理器首先执行实际的读取操作,然后根据读取到的内容进行进一步的处理  
  
写入操作类似于读取操作,只不过第一步注册的是写就绪事件。  
   
  
下面我们来看看Proactor模式中读取操作和写入操作的过程:  
读取操作:  
1. 应用程序初始化一个异步读取操作,然后注册相应的事件处理器,此时事件处理器不关注读取就绪事件,而是关注读取完成事件,这是区别于Reactor的关键。  
  
2. 事件分离器等待读取操作完成事件  
  
3. 在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作(异步IO都是操作系统负责将数据读写到应用传递进来的缓冲区供应用程序操作,操作系统扮演了重要角色),并将读取的内容放入用户传递过来的缓存区中。这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。  
  
4. 事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。  
  
Proactor中写入操作和读取操作,只不过感兴趣的事件是写入完成事件。  
  
从上面可以看出,Reactor和Proactor模式的主要区别就是真正的读取和写入操作是有谁来完成的,Reactor中需要应用程序自己读取或者写入数据,而Proactor模式中,应用程序不需要进行实际的读写过程,它只需要从缓存区读取或者写入即可,操作系统会读取缓存区或者写入缓存区到真正的IO设备.  
   
          综上所述,同步和异步是相对于应用和内核的交互方式而言的,同步 需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。  


如果你想吃一份宫保鸡丁盖饭: 

同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊! 

同步非阻塞:在饭馆点完餐,就去遛狗了。不过溜一会儿,就回饭馆喊一声:好了没啊! 

异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。 

异步非阻塞:饭馆打电话说,我们知道您的位置,一会给你送过来,安心遛狗就可以了。 

“一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作。 
同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO。 
阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。 

同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。 
所以,IO操作可以分为3类:同步阻塞(即早期的IO操作)、同步非阻塞(NIO)、异步(AIO)。 
同步阻塞: 
在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式。 

同步非阻塞: 
在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。 
异步: 
此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序。” 

这段话比较清楚 

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 呵呵什么含义 呵呵的意思有几种 呵呵的含义是什么 呵呵是啥意思 呵呵的意思是什么 呵呵的特殊含义 呵呵呵是什么意思 发呵呵是什么意思 呵呵哒是什么意思 呵呵母猪护崽 呵呵七世有幸 呵呵怎么回复 呵呵是什么意思啊 呵呵是母猪护崽的声音 韩语呵呵怎么写 笑呵呵的意思 拍手唱歌笑呵呵 聊天喜欢用呵呵的人 呵呵用韩语怎么说 论呵呵在网络 韩语呵呵怎么说 呵呵你一脸什么意思 呵呵用日语怎么说 当我说呵呵的时候 发呵呵的意思 呵呵是什么声音 拍手唱歌笑呵呵反思 无聊的时候干什么 无聊怎么办 hehe 度秘 坚果新机四摄曝光呵呵 为什么聊天止于呵呵 呵字开头的成语 一个呵字代表了什么 呵护 呵护的意思 另一种呵护 呵护作文 呵护的拼音 启善呵护膏