IO

15 阅读3分钟

1.IO模型的分类

同步IO

异步IO

阻塞IO

非阻塞IO

BIO

同步阻塞简称BIO

  • 数据的读取和写入总是在一个线程内等待其完成(经典烧开水例子:有一排水壶在烧开水,BIO的工作模式就是叫一个线程停留在一个水壶那,直到这个水壶烧开了为止,再去处理下一个水壶,实际上在等水壶烧开的过程中他什么也没有做)
  • 适应场景:适用于连接数目比较小且固定的架构,这种方式对服务器的资源要求比较高。并发局限在应用中,1.4之前的唯一选择。

NIO

同步非阻塞NIO

  • 同时支持阻塞和非阻塞模式,但是这里我们从同步非阻塞模式来进行说明,什么是同步非阻塞呢?(如果还拿烧开水例子来说,就是叫一个线程不停的轮询每个水壶的状态,看看是否有水壶的状态进行改变,从而进行下一步的操作)
  • 适应场景:连接数量多且连接比较短的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,1.7之后开始支持。

AIO

异步非阻塞AIO

  • 异步非阻塞无需一个线程去轮询,所有的IO操作的状态改变。在相应的状态改变之后,系统会通知对应的线程去进行处理(对应到烧开水中就是,为每一个水壶上面装了一个开关,水烧开之后水壶会自动提醒我们水烧开了)
  • 适应场景:数据连接数多且连接比较长的架构,相册服务器充分调用OS参与并发操作,编程比较复杂

同步与异步的区别

  • 同步:发送一个请求,等待返回,再发送下一个请求。同步可以避免出现死锁,脏读的发生。

  • 异步:发送一个请求,不等待返回,随时可以发送下一个请求。提高效率,保证并发。

阻塞和非阻塞的区别

  • 阻塞:传统的IO流都是阻塞的,也就是说当一个线程调用read()和write()方法时,该线程将被阻塞,直到有些数据读取或被写入。在此期间该线程不能执行其他任何任务,在完成网络通信进行IO时,由于线程会被阻塞,所以服务端必须对每个客户端都提供一个独立的线程进行处理。当服务端要处理大量的客户端的时候性能急剧下降。

  • 非阻塞:JavaNIO是非阻塞的,当线程从某个通道读取数据的时候,若没有数据可用,该线程会去执行其他的任务。线程通常将非阻塞IO的空闲时间用于在其他的通道上执行IO操作,所以单个的线程可以处理多个输入和输出。nio可以让服务器使用一个或者有限的几个线程来同时处理连接到服务器上的所有客户端。