Unix中的5个IO模型和Java中的几种IO原理
基本概念
1、同步和异步
同步:
A调用B,B的处理是同步的,在处理完之前他不会通知A,只有处理完之后才会明确的通知A
异步:
A调用B,B的处理时异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A
总结:
同步和异步最大的区别是被调用方的执行方式和返回时机。同步指的是被调用方做完事情之后再返回,异步指的是调用方先返回,然后再做事情,做完之后再想办法通知调用方
2、阻塞和非阻塞
阻塞:
A调用B,A一直等着B的返回,别的事情什么都不干
非阻塞:
A调用B,A不用一直等着B的返回,先去忙别的事情。
总结:
阻塞和非阻塞最大的区别是在被调用方返回结果之前的这段时间内,调用方是否一直等待。阻塞指的是调用方一直等待别的事情什么都不做,非阻塞指的是调用方先去忙别的事情。
区别:
阻塞、非阻塞说的是调用者,同步、异步说的是被调用者。
Unix中的五种I/O模型
一次I/O访问(read为例),数据(本地、网络)---->操作系统内核的缓冲区---->应用程序的地址空间
两个阶段:
1、等待数据准备
2、将数据从内核拷贝到进程中
1、同步阻塞IO
阶段1:等待数据就绪。网络I/O的情况就是等待远端数据陆续抵达,也就是网络数据被复制到内核缓冲区;磁盘I/O的情况就是等待磁盘数据从磁盘上读取到内核态内存中。
阶段2:数据拷贝。出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中
2、同步非阻塞IO
阶段1:用户进程可选择做其他事情,通过轮询的方式查看内核缓冲区是否就绪。如果数据就绪再去执行阶段2
3、多路复用I/O(select和poll)
指内核一旦发现进程指定的一个或者多个IO条件准备就绪,它就通知该进程。
与同步非阻塞IO不同的是,原来需要用户进程去轮询的这事儿交给了内核线程帮你完成
4、信号驱动I/O(SIGIO)
5、异步非阻塞I/O
用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。
IO两个阶段,用户进程都是非阻塞的
Java流中的几种I/O
1、IO/BIO
BIO就是指IO,即传统的Blocking IO, 即同步并阻塞的IO
依赖于ServerSocket实现,即一个请求对应一个线程,如果线程数不够连接则会等待空余线程或者拒绝连接
2、NIO
Non-Blocking IO,即同步不阻塞的IO
java.nio包下面,核心元素包括Buffer、Channel、Selector
客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询连接,有I/O请求时才会启动一个线程进行处理。它的特点是要不断主动地去询问数据有没有处理完,一般适用于连接数目较大但连接时间较短的应用,如聊天应用。
3、AIO
jdk1.7开始引入,即异步不阻塞的IO
先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间长的应用。
AsynchronousFileChannel: 用于文件异步读写;
AsynchronousSocketChannel: 客户端异步socket;
AsynchronousServerSocketChannel: 服务器异步socket
NIO到Netty
JDK自带的NIO过于复杂,Netty是一个基于NIO的客户、服务端编程框架,Netty简化了网络应用的开发过程。