zoukankan      html  css  js  c++  java
  • BIO、NIO、AIO

    一、扫盲概念

    1、同步与异步

    (1)同步:指一个线程要等待上一个线程执行完之后才开始执行当前的线程。(有一个等待过程)
    (2)异步:指的是一个线程的执行不需要在意其他线程的执行。(没有等待过程)
    (3)同步异步发生在两个(或多个)线程间。
    举例:
      两个人去吃饭,用线程 A 、线程 B 表示。
      同步:线程 A 喊 线程 B 去吃饭,B 听到了就和 A 一起去吃饭。 B 没听到,则 A 就一直喊,直至B听到了,然后与 A 一起去吃饭。
      异步:线程 A 喊 线程 B 去吃饭, 不管 B 有没有听到, A 先去吃饭了,B 可能跟着 A 一起吃饭,也可能过几个小时再去吃饭。

    2、阻塞与非阻塞

    (1)阻塞:指的是调用者发起一个调用请求后,调用者一直等待被调用者处理请求并返回结果,不能进行其他的处理。即当前线程被挂起,无法继续别的处理,需要等待条件满足才会继续处理。
    (2)非阻塞:指的是调用者发起一个调用请求后,调用者不用等待被调用者处理请求的返回结果,可以进行其他的处理。
    (3)阻塞与非阻塞发生在同一线程间。
    举例:
      一个人去食堂吃饭,用线程A表示。
      阻塞:A 来到食堂买饭,某个打菜的窗口有很多人,需要排队等候,此时A只能默默的排队,不能去买其他吃的,直至A来到打菜的窗口。
      非阻塞:A来到食堂买饭,到某个窗口,说出菜名,拿到一张号码,听号取餐,此时A可以去买其他吃的,听到号码后再过来取餐。

    3、并行与并发

    (1)并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时执行。
    (2)并发:通过cpu调度算法,让各线程快速切换。使程序看上去是同时执行的。
    举例:
      两个人吃一碗面,用A、B表示。
      并行:两个人一起吃。
      并发:A先吃一口,B再吃一口,A再吃一口,A再吃一口,B吃一口。

    4、同步与阻塞、异步与非阻塞的区别

    (1)同步、异步发生在不同线程之间。线程间要么同步、要么异步。
    (2)阻塞与非阻塞发生在同一线程间。某个时刻,该线程要么阻塞、要么非阻塞。
    (3)同步和异步是结果,阻塞和非阻塞是过程。
    (4)举例:
      以烧水为例,人为线程A,烧水为线程B。
      同步阻塞:
        上小学的时候烧水,一直在水壶旁边傻等着水开,不知道干些其他的事。
        此时线程A 等待 线程 B 完成,需要在水壶旁边等待,为同步。线程 A 没有干其他的事,等同于线程挂起,为阻塞,即同步阻塞。

      同步非阻塞:
        上中学的时候烧水,知道可以在等水开的时候干些其他的事了(写作业(=_=)),需要等在水壶旁边,只要时不时的看水开了没就行了。
        此时线程A 等待 线程 B 完成,需要在水壶旁边等待,为同步。线程 A 开始写作业(执行其他行为),为非阻塞,即同步非阻塞。

      异步非阻塞:
        上高中的时候烧水,使用电水壶,水开了会发出声音,听到声音了就知道水开了,这期间可以随便干什么事,不需要等在水壶旁边。
        此时线程A 不用等待 线程 B完成,可以不用等在水壶旁边(访问其他线程),听到声音(即线程B结束相关处理并通知线程A),为异步。线程A可以写作业(执行其他行为),为非阻塞,即异步非阻塞。

    5、IO、同步IO、异步IO、阻塞IO、非阻塞IO

    (1)IO(Input/Output),即输入流/输出流。通常指的是对硬盘的读写、外设的读写。

    (2)阻塞IO:阻塞式的IO操作。
      比如:用户线程 向 系统线程 发送一个读请求时,系统线程先检查数据是否就绪,如果未就绪,则一直等待,直至数据就绪。

    (3)非阻塞IO:非阻塞式的IO操作。
      比如:用户线程 向 系统线程 发送一个读请求时,系统线程先检查数据是否就绪,如果未就绪,则会返回一个标志信息通知用户线程当前数据未就绪,通过标志信息判断是否阻塞。

    (4)同步IO:同步的IO操作。
      比如:多个用户线程 向系统线程发送一个读请求时,若数据未就绪,则多个线程不断的去轮询,当某个线程的数据就绪时,拷贝数据,其余线程等待。

    (5)异步IO:异步的IO操作。
      比如:多个用户线程发送读请求后,不管数据就绪未就绪,等数据就绪并拷贝后,再通知用户线程。

    二、BIO

    1、什么是BIO?

      BIO(Blocking Input Output) 指的是 同步阻塞式 IO。
      服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
      适用于连接数目比较小且固定的场景,这种方式对服务器资源要求比较高。

    2、常见的BIO使用

      常用的BIO实现为 : Socket 与 ServerScoket。
      使用一个线程监听客户端的连接。一般通过在while(true) 循环中服务端会调用 accept() 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接。

    【Socket核心代码:】
    Socket s = new Socket("localhost", 8000);
    InputStream is = s.getInputStream();  //is表示服务器端到客户端的流。
    OutputStream os = s.getOutputStream(); //os表示客户端到服务器端的流。
    
    【ServerSocket核心代码:】
    ServerSocket ss = new ServerSocket(8000);
    while(true){
        //accept方法引起当前 主线程main阻塞,等待客户端连接。
        //若连接成功,那么返回一个Socket实例。
        //s代表客户端连接,其有两个属性 in 和 out。
        //in表示客户端发送来的信息, out表示向客户端输出的信息。
        Socket s = ss.accept();
    }

    3、优缺点

    (1)优点:代码简单,直观,维护方便。
    (2)缺点:IO效率极低,影响性能,不使用线程池时可能会严重消耗线程资源。不能处理高并发情况。

    三、NIO

    1、什么是NIO?

      NIO(New Input Output)或者理解为 Non-blocking Input Output,指的是同步非阻塞式IO。
      服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器(Selector)上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
      适合处理连接数目特别多,但是连接比较短(轻操作)的场景。

    2、常见的NIO使用

      常见的NIO实现为:SocketChannel 与 ServerSocketChannel。
      核心:Channel(通道)、Buffer(缓冲区)、Selector(选择器)
      此处使用 JDK 原生的 NIO 过于复杂,可能还有bug,此处不实现。以后再总结。。。
    有兴趣可以参考下面的链接:

    《跟闪电侠学Netty》开篇:Netty是什么?
    https://www.jianshu.com/p/a4e03835921a

    3、NIO与IO的区别

    (1)IO流是阻塞的,NIO流是不阻塞的。
      Java IO的各种流是阻塞的。即当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。
      Java NIO 可以进行非阻塞IO操作,线程进行读操作时,从通道读取数据到缓冲区,同时可以进行其他操作,数据读取到缓冲区后,线程再继续处理数据。写操作类似。

    NIO读写数据的方式:
      从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
      从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。

    (2)IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。
      Java IO操作数据时将数据直接写入或者将数据直接读到 Stream 对象中。Stream 提供了 Buffer开头的包装类,也可以在缓冲区进行操作。
      Java NIO操作数据时将数据直接写入或者将数据直接读到 Buffer 对象中,其数据操作都与缓冲区相关。

    (3)NIO新增的东西(Channel、Selector)
      NIO 通过Channel(通道) 进行读写。通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。
      减少线程的切换,可以提高系统的性能。NIO通过选择器(Selector),使单个线程可以处理多个通道。实现使用较少的线程来处理这些通道。

    四、AIO

    1、什么是AIO?

      AIO(Asynchronous IO),即异步非阻塞式IO。
      NIO 2 ,在Java 7提出,NIO的升级版。
      基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

    平时没怎么使用,以后碰到了再总结。。。


    五、BIO、NIO、AIO使用总结

    1、使用须知

      Java 中的 BIO、NIO和 AIO 是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。

      操作系统IO模型:(未完待续。。。)

        阻塞IO(Blocking IO)
        非阻塞IO(Nonblocking IO)
        I/O复用(I/O Multiplexing)
        信号驱动IO(signal driven I/O)
        异步IO(Asynchronous IO)

    2、比较

    (1)IO,阻塞同步通信模式,基于TCP(客户端与服务端三次握手),简单,吞吐量小。
      核心:Socket和ServerSocket。

    (2)NIO,非阻塞同步通信模式,客户端与服务端通过Channel连接,采用多路复用器(Selector)轮询注册的Channel。
      核心:SocketChannel和ServerSocketChannel。

    (3)AIO,非阻塞异步通信模式,基于事件和回调机制,采用异步通道实现异步通信。
      核心:AsynchronousSocketChannel和AsynchronousServerSocketChannel。

  • 相关阅读:
    对jquery的 attr()和prop()理解
    你真的了解javascript吗
    js代码的一些小技巧
    导出导入数据库
    Mysql授权root用户远程登录
    Centos 忘记root密码怎么办?
    linux挂载概念简述:
    centos7防火墙设置
    centos 防火墙
    centos共享目录
  • 原文地址:https://www.cnblogs.com/l-y-h/p/11592923.html
Copyright © 2011-2022 走看看