当前位置: 移动技术网 > IT编程>开发语言>Java > BIO、NIO、AIO

BIO、NIO、AIO

2019年09月26日  | 移动技术网IT编程  | 我要评论

一、扫盲概念

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。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网