我们知道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. 【相关网站 - 01】- Java 相关网站

    一.官方网站 1. Java 官方网站 https://www.java.com/zh_CN/ 2. Spring 官方网站 http://spring.io/ 1. Spring Framework ...

  2. 13. Roman to Integer (JAVA)

    Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 ...

  3. xmlhttp js 请求

    <html> <script> var xhr = new XMLHttpRequest(); xhr.open('GET', "http://ipinfo.io/j ...

  4. mysql中文查询问题

    alter table t_foo change `str` `str` varchar(100) character set utf8 not null ;

  5. php使用redis的GEO地理信息类型

    redis3.2中增中了对GEO类型的支持,该类型存储经纬度,提供了经纬设置,查询,范围查询,距离查询,经纬度hash等操作. <?php $redis = new Redis(); $redi ...

  6. IIS调试ASP.NET Core项目

    IIS调试ASP.NET Core项目 新建一个ASP.NET Core Web项目,选择API模板或随便一个模板都行 新建一个名为localhost的发布(没试过远程主机,或许也可以),主要设置如下 ...

  7. 《笨方法学Python》加分题17

    题目通过前学习的文件操作把一个文件中的内容拷贝到另一个文件中,并使用 os.path.exists 在拷贝前判断被拷贝的文件是否已经存在,之后由用户判断是否继续完成拷贝. 新知识os.path.exi ...

  8. python 12 模块与包

    一.不知道什么原则 python文件下面只写方法,所有的可直接执行的代码,都放在条件下 原因.该文件有可能被其他文件调用 二.eval() 将字符串转为相应的数据格式可以想象json转为map 三.模 ...

  9. [DBNETLIB][ConnectionOpen(Invalid Instance())] 无效的连接 的解决办法

    Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Data Source=192.168.1.28,1433 连接SQL serve ...

  10. Gym - 101848B Almost AP 暴力

    题目链接:http://codeforces.com/gym/101848/problem/B 给出一串数字要你最多改动三个数字使这一串数字成为等差数列.因为最多改动三个数字所以可以先求出相邻两项的差 ...