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

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

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

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

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

  NIO(N可以理解为new,也可以理解为NonBlock)是新IO,非阻塞IO

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

    在进行文件或者目录操作的时候,可以通过通道或者缓冲区进行数据的读写(同一个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.
       * 直到成功连入服务端或抛异常,阻塞放开

    

关于IO的整理的更多相关文章

  1. socket.io入门整理教程

    socket.io入门整理  发布于 5 年前  作者 dtrex  124983 次浏览  最后一次编辑是 1 年前 我自己在用socket.io开发,对官方网站上的文档,进行简单的整理,然后自己写 ...

  2. WinRT IO相关整理

    虽然一般UWP开发还是依赖.Net for UWP,但有时还是需要调用WinRT API.特别是在IO部分,WinRT有着和.Net似曾相识但又不尽相同的接口.在此对经常用到的一些地方进行一下整理. ...

  3. socket.io入门整理

    我自己在用socket.io开发,对官方网站上的文档,进行简单的整理,然后自己写了一个简单的聊天程序. 最最开始 先安装socket.io: 1 npm install socket.io 利用Nod ...

  4. Java IO流整理Rick

    Java 流IO部分: Console 控制台信息读取// ----------- Console Begin // ------------ 部分代码  Console cons ;  char[] ...

  5. java IO流整理

    Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

  6. IO知识点整理(序列化,管道流,数据流,字节数组流,与编码)

    一:序列化的问题 1.序列号的使用问题 关于在序列化中的序列号的使用问题,一般要是使用. 因为,每次要序列化的类产生都会产生一个一个新的序列号,如果将这个类的程序修改后,就会产生新的序列号,以前序列化 ...

  7. IO知识点整理(文件File类的使用)

    一: 1.API 2.构造函数的程序 注意这集中构造函数的特点. 同时,字段separator的使用. import java.io.File; public class Test101 { publ ...

  8. IO知识点整理(四种基类的使用)

    一:介绍 1.两种基类 字节流 InputStream,OutputStream 字符流 Reader,Writer 二:字符流的基本方法(文字的处理比较常见) 1.Writer的API 2.File ...

  9. Java 持久化之 -- IO 全面整理(看了绝不后悔)

    目录: 一.java io 概述 什么是IO? IO包括输入流和输出流,输入流指的是将数据以字符或者字节形式读取到内存 分为字符输入流和字符输入流 输入流指的是从内存读取到外界 ,分为字符输入流和字节 ...

随机推荐

  1. java第三章多态

    多态: 多态不仅可以减少代码量,还可以提高代码的扩展和可维护性 (通过一个方法可以对所有所需方法一个运用)多态具体表现多种形态能力的特征,同一个实现接口使用不同实例而执行不同的操作 实现多态的三个条件 ...

  2. centos7 安装部署jenkins

    一.简介 jenkins是一个Java开发的开源持续集成工具,广泛用于项目开发,具有自动化构建.测试和部署等功能,它的运行需要Java环境. 二.搭建环境准备:# cat /etc/redhat-re ...

  3. Spring整合quartz关闭,关闭Tomcat Servlet容器时内存泄漏

    出错信息 22-Sep-2017 06:19:51.064 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearR ...

  4. 解决Jenkins用shell脚本部署后,Jenkins自动杀掉启衍生出来的守护进程

    Jenkins部署java项目遇到的问题: 1.Jenkins执行构建后,需要手动执行startup.sh,站点才能正常访问 产生原因: shell脚本发布时,会衍生进程,Jenkins默认会自动杀掉 ...

  5. Python中__init__和self的意义和作用

    由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去.以学生类为例,通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑 ...

  6. hbase-连接流程

    root和meta表 在版本0.9.8之前,存在root表,之后的版本中去除了root表,meta表主要记录了每个表在region的分布情况. meta结构 从表格中可以看出,rowkey格式:tab ...

  7. Kafka 性能测试报告

    Producer command: kafka-producer-perf-test --topic _perf-test --num-records 10000000 --record-size 1 ...

  8. C语言编写程序计算圆上的点的坐标

    Problem Description There is a cycle with its center on the origin. Now give you a point on the cycl ...

  9. Oracle通过SCN做增量备份修复DG

    DG由于网络原因或者bug原因经常不同步,有时隔得时间久了,就会丢失归档日志,或者长时间的归档恢复较慢,有一种可以基于scn的方式来恢复DG库,使用基于scn的增量备份来恢复standby库可以节省大 ...

  10. MySQL数据库时间查询

    /*当前时间加1毫秒*/ SELECT DATE_ADD(NOW(),INTERVAL 1 MICROSECOND); /*当前时间减1毫秒*/ SELECT DATE_ADD(NOW(),INTER ...