关于IO的整理

  咱们知道io只是输入输出,在java语言中分为同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO,如今的IO,通常是用做两种用途:一种是进行文件或者目录的操做(将不一样的输入输出源抽象成流,因此流本质就是从起源到接受的有序数据,即流就是数据),另外一种是进行套接字(Socket)操做(分为ServerSocket——监听其余通信实体链接请求,是服务器端和Socket——链接到制定的服务器,是客户端)。java

  BIO是传统的IO,又称为阻塞性IO编程

    java中的BIO存在两类,一共四个基类,分别是OutputStream/InputStream(字符流),Writer/Reader(字节流),后者两类是为了方便字节操做对前者进  行了封装,底层仍是字符流(具体他们的区别,咱们在后续的博文中比较)。服务器

    在进行文件或者目录操做的时候,将数据的接收方抽象成水管,水管中的水滴就是最小的数据传输单元(对于字节流是一个字节,对于字符流是一个字    符),经过隐式的记录指针来表示当前准备读取水滴的位置,指针自动向后移动,数据接二连三发送,每一个基类中也有对应的方法对指针进行操纵,可是不能操  做读取的方向,BIO数据的传输是单向的,也就是说,不能灵活的操做流中的数据发送的方向架构

    在进行套接字操做的时候,accept()connect()write()read()调用时会产生阻塞。一个请求一个线程,并发太高,线程压力过大,会致使宕机,因此不能应对高并发,高访问量的场景。并发

  NIO(N能够理解为new,也能够理解为NonBlock)是新IO,非阻塞IO异步

    NIO是面向通道(channel)的,面向缓冲区(buffer)的,通道至关于提供了运算环境,缓冲区是运输数据的载体。socket

    在进行文件或者目录操做的时候,能够经过通道或者缓冲区进行数据的读写(同一个channel中既能够读也能够写,是双向的),全部对数据的操做都是通  过缓冲区操做的。函数

    在进行套接字操做的时候,accept()、connect()、write()、read()调用时不会产生阻塞。一个有效请求对应给一个线程,链接没有数据处理就没有线程等待。因此能应对高并发,高访问量的场景。高并发

  AIO是异步IO,Netty在以前的版本中用过,可是如今不用了,如今这项技术尚未具体的行业版。性能

转自其余文章:

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开始支持。

另外,I/O属于底层操做,须要操做系统支持,并发也须要操做系统的支持,因此性能方面不一样操做系统差别会比较明显。

在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操做。

    在比较这两个模式以前,咱们首先的搞明白几个概念,什么是阻塞和非阻塞,什么是同步和异步,同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操做并等待或者轮询的去查看IO操做是否就绪,而异步是指用户进程触发IO操做之后便开始作本身的事情,而当IO操做已经完成的时候会获得IO完成的通知。而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操做的就绪状态来采起的不一样方式,说白了是一种读取或者写入操做函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会当即返回一个状态值。

 通常来讲I/O模型能够分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO

同步阻塞IO:在此种方式下,用户进程在发起一个IO操做之后,必须等待IO操做的完成,只有当真正完成了IO操做之后,用户进程才能运行。JAVA传统的IO模型属于此种方式!

同步非阻塞IO:在此种方式下,用户进程发起一个IO操做之后边可返回作其它事情,可是用户进程须要时不时的询问IO操做是否就绪,这就要求用户进程不停的去询问,从而引入没必要要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。

异步阻塞IO:此种方式下是指应用发起一个IO操做之后,不等待内核IO操做的完成,等内核完成IO操做之后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为何说是阻塞的呢?由于此时是经过select系统调用来完成的,而select函数自己的实现方式是阻塞的,而采用select函数有个好处就是它能够同时监听多个文件句柄,从而提升系统的并发性!

 异步非阻塞IO:在此种模式下,用户进程只须要发起一个IO操做而后当即返回,等IO操做真正的完成之后,应用程序会获得IO操做完成的通知,此时用户进程只须要对数据进行处理就行了,不须要进行实际的IO读写操做,由于真正的IO读取或者写入操做已经由内核完成了。目前Java中尚未支持此种IO模型。

 

注:

  阻塞与非阻塞是指这个方法在执行的时候是否阻塞程序的继续执行其余与客户端和服务器端无关程序。

 

附:BIO阻塞产生与放开的条件

  * accept()会产生阻塞
     * Listens for a connection to be made to this socket and accepts
       * it. The method blocks until a connection is made.
       * 当一个客户端连入的时候,阻塞放开,若是没有客户端连入,就会产生阻塞


  * read()会产生阻塞
       * This method
       * blocks until input data is available, the end of the stream is detected,
       * or an exception is thrown.
       * 当有数据可读时,阻塞放开。


  * write()也会产生阻塞,一直往出写数据,可是没有任何一方读这个数据的时候
       * 写到必定量就会产生阻塞。(是写到网卡的设备缓冲区里)

  * connect()一会产生阻塞,     * Connects this socket to the server with a specified timeout value.       * A timeout of zero is interpreted as an infinite timeout. The connection       * will then block until established or an error occurs.       * 直到成功连入服务端或抛异常,阻塞放开

相关文章
相关标签/搜索