Java BIO、NIO、AIO
同步与异步
同步与异步的概念, 关注的是 消息通信机制
同步是指发出一个请求, 在没有得到结果之前该请求就不返回结果, 请求返回时, 也就得到结果了.
比如洗衣服, 把衣服放在洗衣机里, 没有洗好之前我们一直看着, 直到洗好了才拿出来晾晒.
异步是指发出一个请求后, 立刻得到了回应, 但没有返回结果. 这时我们可以再处理别的事情(发送其他请求), 所以这种方式需要我们通过状态主动查看是否有了结果, 或者可以设置一个回调来通知调用者.
比如洗衣服时, 把衣服放到洗衣机里, 我们就可以去做别的事情, 过会儿来看看有没有洗好(通过状态查询);
或者我们设置洗衣机洗完后响铃来通知我们洗好了(回调通知)
阻塞与非阻塞
阻塞与非阻塞很容易和同步与异步混淆, 但两者关注点是不一样的. 阻塞与非阻塞关注的是 程序在等待调用结果时的状态
阻塞是指请求结果返回之前, 当前线程会被挂起(被阻塞), 这时线程什么也做不了非阻塞是指请求结果返回之前, 当前线程没有被阻塞, 仍然可以做其他事情.
阻塞有个明显的特征就是线程通常是处于BLOCKED状态(BIO中的read()操作时, 线程阻塞是JVM配合OS完成的, 此时Java获取到线程的状态仍是RUNNABLE但它确实已经被阻塞了)
如果要拿同步来做比较的话, 同步通信方式中的线程在发送请求之后等待结果这个过程中应该处于RUNNABLE状态, 同步必须一步一步来完成, 就像是代码必须执行完一行才能执行下一行, 所以必须等待这个请求返回之后才可进行下一个请求, 即使等待结果的时间长, 也是在执行这个请求的过程中. 而异步则不用等上一条执行完, 可以先执行别的代码, 等请求有了结果再来获取结果.
IO模型
Java中的IO操作是JVM配合操作系统来完成的. 对于一个IO的读操作, 数据会先被拷贝到操作系统内核的缓冲区中, 然后从操作系统内核的缓冲区拷贝到应用程序的地址空间. 所以整个过程可分为两个阶段:
- 等待I/O数据准备好. 这取决于IO目标返回数据的速度, 如网络IO时看网速和数据本身的大小.
- 数据从内核缓冲区拷贝到进程内.
根据这两个阶段, 产生了常见的几种不同的IO模型: BIO, NIO, IO多路复用和AIO.
BIO
BIO即Blocking I/O(阻塞 I/O), BIO整个过程如下图:

程序发送请求给内核, 然后由内核去进行通信, 在内核准备好数据之前这个线程是被挂起的, 所以在两个阶段程序都处于挂起状态.
- BIO的特点就是在IO执行的两个阶段都被block了
NIO
NIO即Non-Blocking I/O(非阻塞 I/O), NIO整个过程如下图:

与BIO的明显区别是, 发起第一次请求后, 线程并没有被阻塞, 它反复检查数据是否准备好, 把原来大块不能用的阻塞时间分成了许多”小阻塞”(检查), 所以进程不断有机会被执行. 这个检查有没有准备好数据的过程有点类似于”轮询”.
- NIO的特点就是程序需要不断的主动询问内核数据是否准备好。第一个阶段非阻塞, 第二个阶段阻塞
IO多路复用
IO多路复用(I/O Multiplexing)有select, poll, epoll等不同方式, 它的优点在于单个线程可以同时处理多个网络IO.
NIO中轮询操作是用户线程进行的, 如果把这个任务交给其他线程, 则用户线程就不用这么费劲的查询状态了. IO多路复用调用系统级别的select或poll模型, 由系统进行监控IO状态. select轮询可以监控许多socket的IO请求, 当有一个socket的数据准备好时就可以返回.
- select: 注册事件由数组管理, 数组是有长度的, 32位机上限1024, 64位机上限2048. 轮询查找时需要遍历数组.
- poll: 把select的数组采用链表实现, 因此没了最大数量的限制
- epoll方式: 基于事件回调机制, 回调时直接通知进程, 无须使用某种方式来查看状态.
多路复用IO过程图:

用户线程有一段时间是阻塞的, 从上图来看, 与NIO很像, 但与NIO不一样的是, select不是等到所有数据准备好才返回, 而是只要有一个准备好就返回, 它的优势在于可以同时处理多个连接. 若连接不是很多的话, 它的效率不一定高, 可能还会更差.
Java 1.4开始支持NIO(New IO), 就是采用了这种方式, 在套接字上提供selector选择机制, 当发起select()时会阻塞等待至少一个事件返回.
- 多路复用IO的特点是用户进程能同时等待多个IO请求, 系统来监控IO状态, 其中的任意一个进入读就绪状态, select函数就可以返回.
AIO
AIO即Asynchronous I/O(异步 I/O), 这是Java 1.7引入的NIO 2.0中用到的. 整个过程中, 用户线程发起一个系统调用之后无须等待, 可以处理别的事情. 由操作系统等待接收内容, 接收后把数据拷贝到用户进程中, 最后通知用户程序已经可以使用数据了, 两个阶段都是非阻塞的. AIO整个过程如下图:

AIO属于异步模型, 用户线程可以同时处理别的事情, 我们怎么进一步加工处理结果呢? Java在这个模型中提供了两种方法:
- 一种是基于”回调”, 我们可以实现
CompletionHandler接口, 在调用时把回调函数传递给对应的API即可 - 另一种是返回一个
Future. 处理完别的事情, 可以通过isDone()可查看是否已经准备好数据, 通过get()方法等待返回数据.
小结
上面这几种模式, BIO整个过程都等待返回, NIO和IO多路复用在第二个阶段等待返回, 因此从整个过程来看, 这三个模式都属于同步方式. AIO在整个过程中没有等待返回, 属于异步方式.
Java BIO、NIO、AIO的更多相关文章
- [转帖]JAVA BIO与NIO、AIO的区别(这个容易理解)
JAVA BIO与NIO.AIO的区别(这个容易理解) https://blog.csdn.net/ty497122758/article/details/78979302 2018-01-05 11 ...
- JAVA BIO与NIO、AIO的区别
IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...
- 【转】JAVA BIO与NIO、AIO的区别
Java中IO的模型分为三种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. BIO[同步阻塞] 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个Ser ...
- Java BIO、NIO、AIO 学习(转)
转自 http://stevex.blog.51cto.com/4300375/1284437 先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Ja ...
- JAVA中IO技术:BIO、NIO、AIO
1.同步异步.阻塞非阻塞概念 同步和异步是针对应用程序和内核的交互而言的. 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作 ...
- Java IO 之 BIO、NIO、AIO
1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...
- Java提高班(五)深入理解BIO、NIO、AIO
导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...
- Java网络通信方面,BIO、NIO、AIO、Netty
码云项目源码地址:https://gitee.com/ZhangShunHai/echo 教学视频地址:链接: https://pan.baidu.com/s/1knVlW7O8hZc8XgXm1dC ...
- 以Java的视角来聊聊BIO、NIO与AIO的区别?
转: 以Java的视角来聊聊BIO.NIO与AIO的区别? 飞丫玲丫 17-07-2623:10 题目:说一下BIO/AIO/NIO 有什么区别?及异步模式的用途和意义? BIO(Blocking I ...
- Java BIO、NIO、AIO 学习
正在学习<大型网站系统与JAVA中间件实践>,发现对BIO.NIO.AIO的概念很模糊,写一篇博客记录下来.先来说个银行取款的例子: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO ...
随机推荐
- MySQL中 指定字段排序函数field()的用法
MySQL中的field()函数,可以用来对SQL中查询结果集进行指定顺序排序. 函数使用格式如下: order by (str,str1,str2,str3,str4……),str与str1,str ...
- git撤销commit-hard
场景: 不小心commit了一个不应该commit的修改,但是还没有push,想撤销那个commit 命令: a)git log b)git reset --hard commit_id 具体步骤如下 ...
- ABAP 常见系统表
TRDIRT Program nameTFTIT Function module nameDD02T Table name
- python 递归实现汉诺塔算法
def move(n,a,b,c): if (n == 1): print ( "第 ", n ," 步: 将盘子由 " ,a ," 移动到 &quo ...
- jQuery-弹幕
该方法可能有bug,毕竟简单粗暴 <!DOCTYPE html><html> <head> <meta charset="UTF-8"&g ...
- bash基础特性2
命令别名(alias) ()alias 显示当前shell进程所有可用的命令别名: ()alias NAME='VALUE' 定义别名NAME,相当于执行命令value ()unlias 撤销别名 注 ...
- [转]Examining Open vSwitch Traffic Patterns
In this post, I want to provide some additional insight on how the use of Open vSwitch (OVS) affects ...
- .Net持续集成 —— Jenkins+Git+WebDeploy
由于某些历史问题,最近终于可以从java中解脱出来,继续耕耘.Net了,第一步就是把之前的java项目翻成.net.之前已经实现过一次,翻起来还是比较快的(当然基础架构/实体模型已经重新思考并改进), ...
- 【洛谷4172】 [WC2006]水管局长(LCT)
传送门 洛谷 BZOJ Solution 如果不需要动态的话,那就是一个裸的最小生成树上的最大边权对吧. 现在动态了的话,把这个过程反着来,就是加边对吧. 现在问题变成了怎么动态维护加边的最小生成树, ...
- 程序员跳槽有一份好的简历,offer让你拿到手软
作者:果汁简历 工欲善其事必先利其器,这是自古以来的道理,所以如果想找到一份好的工作,一定要先整理一份好的简历. 模板 写简历首先要有一个好的模板,我们做技术的不同于 UX,UED,我们不需要那么花哨 ...