bio/nio/aio

先看一下这三种的名词解释。
bio:同步阻塞io;
nio:同步非阻塞io;
aio:异步非阻塞io;

通过解释之后,引申出几个概念,什么是同步与异步,什么是阻塞与非阻塞。

同步就是需要自己去监听事件是佛欧有返回结果,而异步是其他线程去做这件事。
阻塞的意思的,比如在bio中,我调用了accept方法,会一直阻塞在这里,直到有连接事件发生,这种酒属于阻塞事件,非阻塞就是在nio中我们调用accept方法,会马上返回结果,线程可以去处理其他事情,这就是非阻塞。

bio模型:

nio模型:

那么为什么netty不使用看上去更高大上的aio,而是使用nio的,其实netty5是使用aio的,但是因为操作系统对aio的支持还不是特别好,而且aio的代码处理逻辑又特别复杂,所以netty5官方不建议使用,现在主流的版本是netty4还是在使用nio的。

多路复用器

当使用bio我们服用断的代码是这样的。

package cn.darwin.base.bio;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;public class BioServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(9001);for (; ; ) {final Socket accept = serverSocket.accept();new Thread(() -> {try {while (true) {byte[] bytes = new byte[1024];final int read = accept.getInputStream().read(bytes);if (read != -1) {System.out.println(new String(bytes));}accept.getOutputStream().write("欢迎".getBytes(StandardCharsets.UTF_8));accept.getOutputStream().flush();}} catch (Exception e) {e.printStackTrace();}}).start();}}
}

在调用accept的时候会堵塞住,做不了其他的操作,这也就是为什么bio会有著名的c10k问题,就是一个服务端连接1W个客户端,性能就会有极大的瓶颈。

而nio将channel设置为非阻塞之后,accept将会立刻返回结果,我们可以将这些个channel放到一个集合中去,然后循环遍历这个list有没有事件发生,即可一个线程处理多个客户端的连接,代码如下:

package cn.darwin.base.nio;import io.netty.buffer.ByteBuf;
import io.netty.channel.ServerChannel;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;public class NioServer {public static void main(String[] args) throws IOException {List<SocketChannel> channelList = new LinkedList<>();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(9002));final Selector open = Selector.open();serverSocketChannel.configureBlocking(false);while (true) {final SocketChannel accept = serverSocketChannel.accept();if (accept != null) {accept.configureBlocking(false);channelList.add(accept);}final Iterator<SocketChannel> iterator = channelList.iterator();while (iterator.hasNext()) {ByteBuffer byteBuffer = ByteBuffer.allocate(1024);final int read = iterator.next().read(byteBuffer);if (read != -1) {System.out.println(new String(byteBuffer.array()));}}}}
}

那么,这样就是比较好的操作了么,假设我们现在一共有100000个链接,每次只有10个左右的连接会有事件发生,我每次要去遍历所有的list么?多路复用器就是我们只去获取那些有事件发生的文件描述符。这种在操作系统层面有几种实现,poll、select、epoll,poll和select还是轮训每个文件操作符看哪个有事件发生,而epoll是在内部维护了一个红黑树和链表,当有数据到达网卡的时候,会触发硬中断,会把这些有事件的放到红黑树中,然后当调用系统函数epoll_wait的时候会将有事件的附件描述符返回。epoll还有两个系统调用,分别是epoll_create和epoll_ctl,分别用于初始化epoll和把文件描述符添加到红黑树中。这就是nio的核心组件selector主要做的事情。

package cn.darwin.base.nio;import io.netty.buffer.ByteBuf;
import io.netty.channel.ServerChannel;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;public class NioServer {public static void main(String[] args) throws IOException {ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(9002));serverSocketChannel.configureBlocking(false);final Selector selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();final Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();if (selectionKey.isAcceptable()) {ServerSocketChannel channel = (ServerSocketChannel)selectionKey.channel();final SocketChannel accept = channel.accept();accept.configureBlocking(false);accept.register(selector,SelectionKey.OP_READ);} else {SocketChannel socketChannel = (SocketChannel)selectionKey.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);final int read = socketChannel.read(byteBuffer);if (read != -1) {System.out.println(new String(byteBuffer.array()));}}iterator.remove();}}}
}

bio/aio/nio以及多路复用器相关推荐

  1. 网络IO发展历程:BIO、NIO、多路复用器、epoll

    网络侧IO,通过网络来通信(偏向内核方面) C10K问题:http://www.kegel.com/c10k.html#frameworks BIO NIO 多路复用器 什么是NIO 操作系统角度:N ...

  2. 内核aio_Java面试题BIO、NIO、AIO有什么区别?

    点击上方"千锋Java学院",选择"置顶公众号" 每天一道面试模拟真题及解析 课前导读 ●回复"每日一练"获取以前的题目,持续更新! ●我希 ...

  3. 面试被问BIO、NIO、AIO的区别,怎么破?

    来源:juejin.cn/post/6844903985158045703 很多文章在谈论到BIO.NIO.AIO的时候仅仅是抛出一堆定义,以及一些生动的例子.看似很好理解.但是并没有将最基础的本质原 ...

  4. 常见的 IO 模型有哪些?Java 中 BIO、NIO、AIO 的区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

  5. BIO与NIO、AIO的区别(这个容易理解)

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在 JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSoc ...

  6. Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  7. 以Java的视角来聊聊BIO、NIO与AIO的区别

    说一说I/O 首先来说一下什么是I/O? 在计算机系统中I/O就是输入(Input)和输出(Output)的意思,针对不同的操作对象,可以划分为磁盘I/O模型,网络I/O模型,内存映射I/O, Dir ...

  8. java基础IO BIO、NIO、AIO的区别

        Java IO(Java数据流)主要就是Java用来读取和输出数据流.它有对应的一系列API.主要是java.io.*,和java.nio.*. Java中IO主要有两类 |-->字节流 ...

  9. 谈谈java的bio、nio、aio模型

    目录 socket IO(BIO)和NIO的区别 同步和异步 bio:同步阻塞式IO NIO:同步非阻塞IO(工作中用的很少) Buffer使用 NIO代码 AIO socket Socket又称&q ...

最新文章

  1. IT人的学习方法论-续集 关于英语的学习
  2. 偶遇mysql(Percona Server)的一个新bug
  3. JAVA线程间协作:Condition
  4. Django接入paypal的账户-准备工作
  5. 数据结构--栈 codevs 1107 等价表达式
  6. CompletionService VS ExecutorService
  7. Uva1343-The Rotation Game-IDA*算法
  8. 十分钟-Nginx入门到上线
  9. 使用iftop监控网卡实时流量
  10. stm32芯片超时无应答解决
  11. 小程序跳转至企业微信客服wx.openCustomerServiceChat
  12. 和橘子菇凉一起开始python之旅吧!
  13. 产品破局思考:一个思维,一种策略
  14. 电话销售话术模板有哪些 电话销售技巧
  15. TensorFlow基础(1)特点安装基本用法
  16. C语言练习题,大小写字母转换,ASC码的输出
  17. LDPC码动态调度算法
  18. CPU中虚拟地址、逻辑地址(有效地址)、线性地址、物理地址
  19. 【伯克利马毅老师】强化学习与最优控制综述
  20. 使用Spring实现Redis的发布/订阅功能

热门文章

  1. 屏幕偏色的原因及解决方法
  2. Unity场景内模型出现粉色的处理方法
  3. 读书笔记:你就是极客-软件开发人员生存指南
  4. Latex公式放符号正下方
  5. 创业赢利模式之三包装生产模式
  6. 使用html+css+jQuery做一个每日任务列表
  7. 简书Android APP上线了
  8. 给简书找BUG赢好礼17.06.02——简书Android 2.4.0 公测【私密文章支持预览/手机支持直接提现】...
  9. 元宇宙退潮,人工智能起飞,大厂 Al 新赛点在哪?
  10. 【react】上传头像或图片列表组件的实现