IO多路复用IO多路复用(I/O Multiplexing)有select, poll, epoll等不同方式, 它的优点在于单个线程可以同时处理多个网络IO.
NIO中轮询操作是用户线程进行的, 如果把这个任务交给其他线程, 则用户线程就不用这么费劲的查询状态了. IO多路复用调用系统级别的select或poll模型, 由系统进行监控IO状态. select轮询可以监控许多socket的IO请求, 当有一个socket的数据准备好时就可以返回.
- select: 注册事件由数组管理, 数组是有长度的, 32位机上限1024, 64位机上限2048. 轮询查找时需要遍历数组.
- poll: 把select的数组采用链表实现, 因此没了最大数量的限制
- epoll方式: 基于事件回调机制, 回调时直接通知进程, 无须使用某种方式来查看状态.
多路复用IO过程图:
用户线程有一段时间是阻塞的, 从上图来看, 与NIO很像, 但与NIO不一样的是, select不是等到所有数据准备好才返回, 而是只要有一个准备好就返回, 它的优势在于可以同时处理多个连接. 若连接不是很多的话, 它的效率不一定高, 可能还会更差.
Java 1.4开始支持NIO(New IO), 就是采用了这种方式, 在套接字上提供selector选择机制, 当发起select()时会阻塞等待至少一个事件返回.
- 多路复用IO的特点是用户进程能同时等待多个IO请求, 系统来监控IO状态, 其中的任意一个进入读就绪状态, select函数就可以返回.
AIOAIO即Asynchronous I/O(异步 I/O), 这是Java 1.7引入的NIO 2.0中用到的. 整个过程中, 用户线程发起一个系统调用之后无须等待, 可以处理别的事情. 由操作系统等待接收内容, 接收后把数据拷贝到用户进程中, 最后通知用户程序已经可以使用数据了, 两个阶段都是非阻塞的. AIO整个过程如下图:
AIO属于异步模型, 用户线程可以同时处理别的事情, 我们怎么进一步加工处理结果呢? Java在这个模型中提供了两种方法:
- 一种是基于”回调”, 我们可以实现CompletionHandler接口, 在调用时把回调函数传递给对应的API即可
- 另一种是返回一个Future. 处理完别的事情, 可以通过isDone()可查看是否已经准备好数据, 通过get()方法等待返回数据.
小结上面这几种模式, BIO整个过程都等待返回, NIO和IO多路复用在第二个阶段等待返回, 因此从整个过程来看, 这三个模式都属于同步方式. AIO在整个过程中没有等待返回, 属于异步方式. |