NIO、BIO、AIO

https://gitee.com/jly521/NioAio.git  NIO、AIO代码举例地址git

  • 从进程级通讯的维度讨论时, 阻塞和同步(非阻塞和异步)就是一对同义词, 且须要针对发送方接收方做区分对待。
    • 发送方阻塞/非阻塞(同步/异步)和接收方的阻塞/非阻塞(同步/异步) 是互不影响的。

#############################个人理解编程

同步和异步(宏观表现):后端

  • 异步能主动通知你,不用你不停的轮询
  • 同步的含义是,你是否须要亲自去处理数据

阻塞非阻塞(具体实现):缓存

  • 调用不能直接返回结果,所采起的策略(等仍是不等)

BIO(同步阻塞):服务器

  • 好比发起读入操做,若是获取不到就会阻塞等待返回结果,整个程序挂起。

NIO(同步非阻塞):网络

  • channel、selector、buffer
  • 好比发起读入操做,调用handler
    • 若是获取不到就会返回读取不到状态(好比被锁),整个程序挂起,过一段时间轮询好了没
    • 若是获取到读入缓存,开启读取动做
  • 使用 select轮询就是同步

  • 每次从选中的通道读取数据能够设置阻塞和非阻塞策略,读入缓存

AIO,即NIO2.0(异步非阻塞):多线程

  • 好比发起读入操做,
    • 若是读取不到,根本不会调用handler
    • 若是获取到读入缓存,调用handler处理
  • aio 接收客户端请求才去的是读入完成后回调处理函数,因此是异步

  • 建立的AsynchronousSocketChannel通道,名字不难看出是异步通道(非阻塞)

@@@@@@@@@@@@@@@@@@@@@@@@@@架构

IO的方式一般分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。并发

BIO框架

  •  在JDK1.4出来以前,咱们创建网络链接的时候采用BIO模式
  • 须要先在服务端启动一个ServerSocket,而后在客户端启动Socket来对服务端进行通讯,默认状况下服务端须要对每一个请求创建一堆线程等待请求
  • 而客户端发送请求后,先咨询服务端是否有线程相应,若是没有则会一直等待或者遭到拒绝请求,若是有的话,客户端会线程会等待请求结束后才继续执行。

伪异步I/O编程

  • 采用线程池和任务队列能够实现一种叫作伪异步的I/O通讯框架。

NIO

  • NIO自己是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题: 
  • 将每个客户端请求分配给一个线程来单独处理。
    • 操做系统自己也对线程的总数有必定的限制。
    • 若是客户端的请求过多,服务端程序可能会由于不堪重负而拒绝客户端的请求,甚至服务器可能会所以而瘫痪。

BIO与NIO一个比较重要的不一样

  • 是咱们使用BIO的时候每每会引入多线程,每一个链接一个单独的线程;
  • 而NIO则是使用单线程或者只使用少许的多线程,每一个链接共用一个线程。

  • NIO的最重要的地方是当一个链接建立后,不须要对应一个线程,这个链接会被注册到多路复用器上面
    • 因此全部的链接只须要一个线程就能够搞定,
    • 当这个线程中的多路复用器进行轮询的时候,发现链接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式
  • 在NIO的处理方式中,
    • 当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC链接等),其实这个线程就被阻塞了,
    • 当并发上来的话,仍是会有BIO同样的问题。

AIO

  • 与NIO不一样,当进行读写操做时,只须直接调用API的read或write方法便可。
  • 这两种方法均为异步的,对于读操做而言,当有流可读取时,操做系统会将可读的流传入read方法的缓冲区,并通知应用程序;
  • 便可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。 

汇总图:

先来个例子理解一下概念,以银行取款为例: 

  • 同步 : 本身亲自出马持银行卡到银行取钱(使用同步IO时,Java本身处理IO读写);
  • 异步 : 委托一小弟拿银行卡到银行取钱,而后给你(使用异步IO时,Java将IO读写委托给OS处理,须要将数据缓冲区地址和大小传给OS(银行卡和密码),OS须要支持异步IO操做API);
  • 阻塞 : ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回);
  • 非阻塞 : 使用非阻塞IO时,若是不能读写Java调用会立刻返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成。

Java对BIO、NIO、AIO的支持:

  • Java BIO : 同步并阻塞,服务器实现模式为一个链接一个线程,
    • 即客户端有链接请求时服务器端就须要启动一个线程进行处理,
    • 若是这个链接不作任何事情会形成没必要要的线程开销,固然能够经过线程池机制改善。
  • Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,
    • 即客户端发送的链接请求都会注册到多路复用器上,
    • 多路复用器轮询到链接有I/O请求时才启动一个线程进行处理。
  • Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,
    • 客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,

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

  • BIO方式适用于链接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的惟一选择,但程序直观简单易理解。
  • NIO方式适用于链接数目多且链接比较短(轻操做)的架构,好比聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
  • AIO方式使用于链接数目多且链接比较长(重操做)的架构,好比相册服务器,充分调用OS参与并发操做,编程比较复杂,JDK7开始支持。

同步和异步是针对应用程序和内核的交互而言的。 

  • 同步/异步是在时间上强调处理事情的结果/机会成本的两种处理策略;

阻塞和非阻塞是针对于进程在访问数据的时候

  • 阻塞方式下读取或者写入函数将一直等待,
  • 而非阻塞方式下,读取或者写入函数会当即返回一个状态值。

同步/异步是宏观上(进程间通信,一般表现为网络IO的处理上),

  • 阻塞/非阻塞是微观上(进程内数据传输,一般表现为对本地IO的处理上);
  • 阻塞和非阻塞是同步/异步的表现形式

相关文章
相关标签/搜索