javaNIO--前述I/O模型
来源:互联网 发布:网络信息安全培训ppt 编辑:程序博客网 时间:2024/04/29 17:33
概念
在讲解NIO之前,先了解一下I/O的一些基本概念,这些概念经常会遇到,也经常会被混淆。
同步和异步
同步: 当有多个任务或者事件同时发生时,这些任务或者事件比较逐个执行,一个任务或事件的执行必然导致整个流程暂时等待,这些任务无法并行执行。
异步: 当有多个任务或者事件同时发生时,这些任务或者事件可以同时执行,一个事件的执行不会导致整个流程的停滞。
例如,下面这段代码就是同步
void function(){ fun1(); fun2() ..... ..... }
而下面这段就是异步
void function(){ new Thread(){ public void run() { fun1(); } }.start(); new Thread(){ public void run() { fun2(); } }.start();}
* 同步和异步范围比较大,指的是执行的任务或者事件 *
阻塞和非阻塞
阻塞:当我们执行一个任务的中的一个请求时,这个请求需要的数据资源没有准备好,那么当前任务就会一直等待,直到数据准备好为止。
非阻塞:当我们执行一个请求时,这个请求需要的条件没有满足,那么不会一直等待,而是立刻返回一个标志信息告诉说条件不满足。
所以两者的区别主要在于当条件不满足时是一直等待,还是返回不满足的标志信息。
* 阻塞和非阻塞的范围就变小了,他们指的是一个任务中具体的一个请求 *
阻塞IO和非阻塞IO
IO指的就是磁盘、硬盘、外接设备的读写,包括socket的读写等
阻塞IO: 当发起一个IO请求时,内核会去检查请求数据是否就绪,如果没有就绪就会一直等待,直到数据准备就绪。
非阻塞IO:当发起一个IO请求时,内核会去检查请求的数据是否就绪,如果没有就绪会立刻返回一个标志信息告诉用户没有就绪,等数据就绪后内核会将数据拷贝到用户线程,完成最终的IO操作请求。
所以完成的IO操作包括两个阶段
检查数据完备性
进行数据拷贝,由内核将数据拷贝到用户线程
* 阻塞IO和非阻塞IO范围进一步缩小,指的是一次阻塞或者非阻塞请求中的IO请求 *
同步IO和异步IO
同步IO:当发起一个IO请求后,如果数据没有准备好,那么用户线程或者内核会轮询检查数据是否已经完备,当数据就绪后,在将数据拷贝到用户线程中继续执行。
异步IO : 用户线程只发起IO请求,内核会自己完成后续的操作请求,然后发送通知告知用户线程IO操作已经完成。也就是说在异步IO中,不会对用户线程产生任何阻塞
同步IO和异步IO的关键区别反映在数据拷贝阶段是由用户线程完成还是内核完成。所以说异步IO必须要有操作系统的底层支持。
IO模型
阻塞IO模型
通常我们使用到的都是阻塞IO,即当我们发起一个IO请求时,数据没有就绪时,用户线程会处于阻塞状态交出cup的使用权,当数据就绪后内核会将数据拷贝到用户线程中,并返回结果给用户线程,用户线程才会接着执行。
非阻塞IO
当我们发起一个IO请求时,如果数据没有就绪会立刻返回一个未就绪的结果给用户,这个时候用户需要轮询发起IO请求,不断的检查返回标识的状态,当数据就绪并且接收到IO请求时,内核会将数据拷贝到用户线程池,用户线程会接着执行。
也就是说非阻塞IO需要我们不断的轮询发起请求,因此用户线程不会交出CUP的使用权
但是由于一直在轮询发起请求,一旦这个请求是一个长连接,那么cup的使用率会急速上升。
多路复用IO
多路复用IO是目前使用最多的,Java的NIO就是使用的多路复用IO模型
以socket为例,多路复用IO就是会有一个线程不断的轮询socket请求,当轮询到有socket的读写请求时,才会创建一个线程去执行请求。
因此在多路复用IO中只需要一个线程就可以管理多个socket,而且不会新创建线程,也不用维护和管理这些线程,只有请求发生的时候才会使用IO资源,大大节约了资源
它比非阻塞IO的优势就是,非阻塞IO的轮询socket的状态是由用户线程在执行的,而多路复用IO的socket状态的轮询是内核完成的,效率上非常高。
在Java的NIO中,是通过Selector.select()来检查通道是否有事件的,没有事件则会一直阻塞,因此NIO是会导致用户线程的阻塞。
多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。
信号驱动IO
在用户发起一个IO请求时,会在请求上注册一个信号函数,然后用户线程会接着执行,当内核将数据拷贝到用户线程后,会发送一个信号给用户线程,然后用户线程会执行注册的信号函数完成IO操作请求。
异步IO
当用户发起一个IO请求后,用户线程不会被阻塞,可以接着往下执行,所有IO操作都有内核去完成,当内核完成IO操作后会发送一个信号给用户线程,告诉用户IO操作已经完成后,这个时候就可以直接使用数据了。
与信号渠道IO不同的是,用户只需要发起一个IO请求,所有的操作都是由内核完成的,内核只需要发送一个完成信号就行了,而信号渠道IO在接收到信号后还需要用户线程去处理IO操作
异步IO才是最理想化的IO模型
前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。
- javaNIO--前述I/O模型
- winsock I/O模型
- 重叠I/O模型
- 重叠I/O模型
- 重叠I/O模型
- I/O模型
- 重叠I/O模型
- Socket I/O模型
- I/O模型
- Socket I/O模型
- I/O 模型
- Unix I/O模型
- Unix I/O 模型
- 重叠I/O模型
- I/O模型
- I/O模型
- I/O 模型
- 网络I/O模型
- 前端九段,你是哪一段?
- Python学习
- 1204: 华科版C语言程序设计教程(第二版)课后习题3.8
- java总结系列之四(内存)
- typeof VS instanceof
- javaNIO--前述I/O模型
- JAVA开发工具整理
- 初次使用Frament发生报错
- Android O之通知
- 详解SQL Server连接(内连接、外连接、交叉连接)
- 16.1.5 控制实例化
- Linux umask默认值
- vue环境搭建
- tomcat server.xml