BIO NIO AIO之间的区别

一、BIO、NIO、AIO的基本定义与类比描述:

BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里使用那个经典的烧开水例子,这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了

二、进程中的IO调用步骤大致可以分为以下四步:

1.进程向操作系统请求数据 ;

2.操作系统把外部数据加载到内核的缓冲区中;

3.操作系统把内核的缓冲区拷贝到进程的缓冲区 ;

4.进程获得数据完成自己的功能 ;

当操作系统在把外部数据放到进程缓冲区的这段时间(即上述的第二,三步),如果应用进程是挂起等待的,那么就是同步IO,反之,就是异步IO,也就是AIO 。

三、各自的特点

1)BIO(Blocking I/O)同步阻塞I/O 

会阻塞每一个线程

在高并发的web或者tcp服务器中采用BIO模型就无法应对了,如果系统开辟成千上万的线程,那么CPU的执行时机都会浪费在线程的切换中,使得线程的执行效率大大降低。

2)NIO (New I/O) 同步非阻塞I/O 

只阻塞一个线程

NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:

– NIO是基于块(Block)的,它以块为基本单位处理数据

– 为所有的原始类型提供(Buffer)缓存支持

– 增加通道(Channel)对象,作为新的原始 I/O 抽象

– 支持锁和内存映射文件的文件访问接口

– 提供了基于Selector的异步网络I/O

关于NIO弄清除 Channel、Buffer、Selector三个类之间的关系就可以了

Channel

首先说一下Channel,国内大多翻译成“通道”。Channel和IO中的Stream(流)是差不多一个等级的。只不过Stream是单向的,譬如:InputStream, OutputStream。而Channel是双向的,既可以用来进行读操作,又可以用来进行写操作,NIO中的Channel的主要实现有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel;通过看名字就可以猜出个所以然来:分别可以对应文件IO、UDP和TCP(Server和Client)。

Buffer

NIO中的关键Buffer实现有:ByteBuffer、CharBuffer、DoubleBuffer、 FloatBuffer、IntBuffer、 LongBuffer,、ShortBuffer,分别对应基本数据类型: byte、char、double、 float、int、 long、 short。

Selector

Selector 是NIO相对于BIO实现多路复用的基础,Selector 运行单线程处理多个 Channel,如果你的应用打开了多个通道,但每个连接的流量都很低,使用 Selector 就会很方便。例如在一个聊天服务器中。要使用 Selector , 得向 Selector 注册 Channel,然后调用它的 select() 方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新的连接进来、数据接收等。

 1 import java.io.IOException;
 2 import java.net.InetSocketAddress;
 3 import java.nio.channels.SelectionKey;
 4 import java.nio.channels.Selector;
 5 import java.nio.channels.ServerSocketChannel;
 6 import java.util.Iterator;
 7
 8 public class TCPServerSelector{
 9     //缓冲区的长度
10     private static final int BUFSIZE = 256;
11     //select方法等待信道准备好的最长时间
12     private static final int TIMEOUT = 3000;
13     public static void main(String[] args) throws IOException {
14         if (args.length < 1){
15             throw new IllegalArgumentException("Parameter(s): <Port> ...");
16         }
17         //创建一个选择器
18         Selector selector = Selector.open();
19         for (String arg : args){
20             //实例化一个信道
21             ServerSocketChannel listnChannel = ServerSocketChannel.open();
22             //将该信道绑定到指定端口
23             listnChannel.socket().bind(new InetSocketAddress(Integer.parseInt(arg)));
24             //配置信道为非阻塞模式
25             listnChannel.configureBlocking(false);
26             //将选择器注册到各个信道
27             listnChannel.register(selector, SelectionKey.OP_ACCEPT);
28         }
29         //创建一个实现了协议接口的对象
30         TCPProtocol protocol = new EchoSelectorProtocol(BUFSIZE);
31         //不断轮询select方法,获取准备好的信道所关联的Key集
32         while (true){
33             //一直等待,直至有信道准备好了I/O操作
34             if (selector.select(TIMEOUT) == 0){
35                 //在等待信道准备的同时,也可以异步地执行其他任务,
36                 //这里只是简单地打印"."
37                 System.out.print(".");
38                 continue;
39             }
40             //获取准备好的信道所关联的Key集合的iterator实例
41             Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
42             //循环取得集合中的每个键值
43             while (keyIter.hasNext()){
44                 SelectionKey key = keyIter.next();
45                 //如果服务端信道感兴趣的I/O操作为accept
46                 if (key.isAcceptable()){
47                     protocol.handleAccept(key);
48                 }
49                 //如果客户端信道感兴趣的I/O操作为read
50                 if (key.isReadable()){
51                     protocol.handleRead(key);
52                 }
53                 //如果该键值有效,并且其对应的客户端信道感兴趣的I/O操作为write
54                 if (key.isValid() && key.isWritable()) {
55                     protocol.handleWrite(key);
56                 }
57                 //这里需要手动从键集中移除当前的key
58                 keyIter.remove();
59             }
60         }
61     }
62 }

3)AIO (Asynchronous I/O) 异步非阻塞I/O 

不阻塞任何线程

  • 读完了再通知我
  • 不会加快IO,只是在读完后进行通知
  • 使用回调函数,进行业务处理
 1 public static void main(String[] args) throws IOException {
 2
 3     AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0000));
 4     server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
 5         final ByteBuffer buffer = ByteBuffer.allocate(1024);
 6
 7         @Override
 8         public void completed(AsynchronousSocketChannel result, Object attachment) {
 9             System.out.println(Thread.currentThread().getName());
10             Future<Integer> writeResult = null;
11             try {
12                 buffer.clear();
13                 result.read(buffer).get(100, TimeUnit.SECONDS);
14                 buffer.flip();
15                 writeResult = result.write(buffer);
16             } catch (InterruptedException | ExecutionException e) {
17                 e.printStackTrace();
18             } catch (TimeoutException e) {
19                 e.printStackTrace();
20             } finally {
21                 try {
22                     server.accept(null, this);
23                     writeResult.get();
24                     result.close();
25                 } catch (Exception e) {
26                     System.out.println(e.toString());
27                 }
28             }
29         }
30
31         @Override
32         public void failed(Throwable exc, Object attachment) {
33             System.out.println("failed: " + exc);
34         }
35     });
36
37 }

原文地址:https://www.cnblogs.com/756623607-zhang/p/9181003.html

时间: 2024-10-09 15:33:01

BIO NIO AIO之间的区别的相关文章

2020-4-8小结 BIO,NIO,AIO 有什么区别?

对于这几种I/O在面试是总是我的混淆点,在此看过javaGuide哥的面试宝典后,在此总结记录. 1.BIO (Blocking I/O): 同步阻塞 I/O 模式,数据的读取写入必须阻塞在一个线程内等待其完成.在活动连接数不是特别高(小于单机 1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载.限流等问题.而且线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求.但是,当面对十万甚至百万级连接的时候,传统的

BIO NIO AIO区别

JAVA 中BIO,NIO,AIO的理解 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下:  序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 散仙不才,在查了一部分资料后,愿试着以通俗易懂的方式解释下这几个名词.如有不足之处,还望告知. 在弄清楚上面的几个问题之前,我们首先得明白什么是同步,异步,阻塞,非阻塞,只有这几个单个概念理解清楚了,

Netty5序章之BIO NIO AIO演变

Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用的技术.更是面试的加分项.Netty并非横空出世,它是在BIO,NIO,AIO演变中的产物,是一种NIO框架.而BIO,NIO,AIO更是笔试中要考,面试中要问的技术.也是一个很好的加分项,加分就是加工资,你还在等什么?本章带你细细品味三者的不同! 流程图: 技术:BIO,NIO,AIO 说明:g

初理解Java中的BIO,NIO,AIO

初识: java 中的 BIO.NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装.程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码.只需要使用Java的API就可以了. 在讲 BIO,NIO,AIO 之前先来回顾一下这样几个概念:同步与异步,阻塞与非阻塞. 同步与异步: 同步: 同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回. 异步: 异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但

JAVA 中BIO,NIO,AIO的理解

JAVA 中BIO,NIO,AIO的理解 博客分类: 网络编程 [转自]http://qindongliang.iteye.com/blog/2018539 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 散仙不才,在查了一部分资料后,愿试着以通俗易懂的方式解释下这几个名词.如有不足之处,还

也谈BIO | NIO | AIO (Java版--转)

关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个层面: 编程语言 实现原理 底层基础 从编程语言层面 BIO | NIO | AIO 以Java的角度,理解,linux c里也有AIO的概念(库),这些概念不知道什么原因被炒火起来,这里只从Java角度入手. BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一

转载:BIO | NIO | AIO

http://my.oschina.net/bluesky0leon/blog/132361 也谈BIO | NIO | AIO (Java版) 转载自:zheng-lee博客 发布时间: 2013/05/21 12:56 关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个层面: 编程语言 实现原理 底层基础 从编程语言层面 BIO | NIO |

拿搬东西来解释udp tcpip bio nio aio aio异步

[群主]雷欧纳德简单理解 tcpip是有通信确认的面对面通信   有打招呼的过程  有建立通道的过程 有保持通道的确认    有具体传输 udp是看到对面的人好像在对面等你 就往对面扔东西[群主]雷欧纳德基本上 好比从货车a  运东西到货车b   tcpip是建立人手互传的方式   udp是 a货车里搬出的东西直接往b货车的人方向扔  你接成功没有  散架没 我扔的一方不管的 tcp管这个 ip是通道[群主]雷欧纳德ip是手语  高速对面 我在等你  或者我要发过来了 这一类的 [群主]雷欧纳德

JAVA中的BIO,NIO,AIO

在了解BIO,NIO,AIO之前先了解一下IO的几个概念: 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪, 例如自己亲自出马持银行卡到银行取钱 2.异步 用户触发IO操作以后,可以干别的事,IO操作完成以后再通知当前线程,例如让小弟去银行帮你取钱,你可以干别的事 3.阻塞 当试图进读写文件的时候,发现不可读取或没东西读,则进入等待状态知道可读,ATM排队取钱 4.非阻塞 用户进程访问数据时,会马上返回一个状态值(可读不可读),比如在银行柜台办理业务,先取个号,然后坐在椅子