Java中5种IO模型分别是什么?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1923个文字,预计阅读时间需要8分钟。
每日一句:人的痛苦会把自身折磨到多深呢?每日一句:You cannot swim for new horizons until you have courage to lose sight of the shore. 除了有勇气离开岸边,否则你永远游不到彼岸。概念:IO是主存和外存。
每日一句人的痛苦会把自己折磨到多深呢?
每日一句You cannot swim for new horizons until you have courage to lose sight of the shore.
除非有勇气离开岸边,否则你永远游不到彼岸。
IO是主存和外部设备(硬盘、终端和网络等)拷贝数据的过程。IO是操作系统的底层功能实现,底层通过I/O指令进行完成。
以下是5种类Unix下可用的I/O模型
1.阻塞式I/O:BlockingIO
2.非阻塞式I/O:nonblockingIO
3.I/O复用(Select,pollepoll):IOmultiplexing
4.信号驱动式I/O(SIGIO):signaldrivenIO
5.异步I/O(posix的 aio系列函数):asynchromousIO
Blocking IO在Linux中,默认情况下所有的socket都是Blocking,一个典型的读操作流程大概是这样:
1.通常涉及等待数据从网络到达。当所有等待数据到达时,它被复制到内核中的某个缓冲区
2.把数据从内核缓冲区复制到应用程序缓冲区
当用户进程调用了 recvfrom这个系统调用, kernel就开始了IO的第一个阶段:准备数据。对于networkIO来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包)。这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。
所以,BlockingIO的特点就是在IO执行的两个阶段都被block了
Linux下,可以用过设置socket使其变为non-blocking。当对一个non-blockingsocket执行操作时,流程如下:
从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。 从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次 发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
所以,用户进程第一个阶段不是阻塞的,需要不断的主动询问kernel数据好了没有;第二个阶段依然总是阻塞的。
IO 多路复用(NIO)select、epoll的好处就在于单个process就可以同时处理多个网络链接的IO。
IO复用和同步阻塞本质一样,不过利用了新的Select系统调用,由内核来负责本来是请求进程该做的轮训操作,看似不非阻塞IO还多了哥系统调用开销,不过因为支持多路IO才算提高了效率
也就是一个可以监听多个。
它的基本原理就是select、epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如下图:
当用户线程调用select,那么整个进程会被阻塞,而同时,kernel会监视所有select负责的socket =,当任何一个socket中的数据准备好了,select就会返回,这个时候用户进程会调用read操作,将数据kernel拷贝到用户进程。
首先开启套接字的信号驱动式IO功能,并且通过sigaction(信号处理程序) 系统调用安装一个信号处理函数 ,该函数调用将立即返回,当前进程没有被阻塞 ,继续工作;当数据报准备好的时候,内核为该进程产生SIGIO 的信号,随后既可以在信号处理函数中调用recvfrom 读取数据报,并且通知主循环数据已经准备好等待处理;也可以直接通知主循环让它读取数据报;(其实就是一个待读取的通知和待处理的通知),基本不会用到。
多线程和多进程的模型虽然解决了并发的问题,但是系统不能无限的增加线程,由于系统的切换线程的开销恒大,所以,一旦线程数量过多,CPU的时间就花在线程的切换上,正真运行代码的时间就会减少,结果导致性能严重下降
由于我们要解决的问题是CPU高速执行能力和IO设备的龟速严重不匹配,多线程和多进程只是解决这一个问题的一种方法。
另一种解决IO问题的方法是异步IO,当代码需要执行一个耗时的IO操作时,他只发出IO指令,并不等待IO结果然后就去执行其他代码,一段时间后,当IO返回结果是,在通知CPU进行处理我们调用aio_read函数,给内核传递描述符,缓冲区指针,缓冲区大小,和文件偏移量,并且告诉内核当整个操作完成时如何通知我们,该函数调用后,立即返回,不会被阻塞
另一方面:从kernel的角度,当他收到一个aio_read之后,首先它立即返回,所以不会对用户进程产生block,然后kernel会等待数据准备完成,然后将数据拷贝到用户内存(copy由内核完成),当着一切完成后,kernel会给用户进程发送一个singal或者执行下一个基于线程回调函数来完成此次IO处理过程,告诉他read操作完成
美文佳句岁月应是静好。近来,心神总是不宁,想必是被尘世间的诱惑所困。
我想,要是远方的祥夫先生来到我这“梅知堂”,两人清茶一杯,盘腿而坐,或看他画梅,纸上的梅花仿佛兀自开在飞雪里,如是,那该是一幅怎样的墨梅图?
昨晚,梦里看到那个戴着小黑圆眼镜的祥夫背着黄色的大包正往江南赶路。是又到了梅花开的日子了吗?
面试题 SpringMVC工作原理?1.客户端发送请求到前端控制器DispatcherServlet
2.DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取handler
3.处理器映射器根据url找到具体的处理器,生成处理器对象以及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
4.DispatcherServlet调用HandlerAdapter处理器适配器
5.HandlerAdapter经过适配器调用具体处理器(Handler,也叫后端控制器)
6.Handler执行完成返回ModelAndView
7. HandlerAdaper将Handler执行结果ModelAndView返回给DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析
9.ViewResolver解析后返回具体View
10.DispatcherServlet对view进行渲染视图(即将模型数据填充至视图中)
11.DispatcherServlet响应用户
ArrayList 、LinkedList和Vector的区别?
@RestController 注解,在 @Controller 基础上,增加了 @ResponseBody 注解,更加适合目前前后端分离的架构下,提供 Restful API ,返回例如 JSON 数据格式。当然,返回什么样的数据格式,根据客户端的 "ACCEPT" 请求头来决定。
你好,我是yltrcc,日常分享技术点滴,欢迎关注我:ylcoder
本文共计1923个文字,预计阅读时间需要8分钟。
每日一句:人的痛苦会把自身折磨到多深呢?每日一句:You cannot swim for new horizons until you have courage to lose sight of the shore. 除了有勇气离开岸边,否则你永远游不到彼岸。概念:IO是主存和外存。
每日一句人的痛苦会把自己折磨到多深呢?
每日一句You cannot swim for new horizons until you have courage to lose sight of the shore.
除非有勇气离开岸边,否则你永远游不到彼岸。
IO是主存和外部设备(硬盘、终端和网络等)拷贝数据的过程。IO是操作系统的底层功能实现,底层通过I/O指令进行完成。
以下是5种类Unix下可用的I/O模型
1.阻塞式I/O:BlockingIO
2.非阻塞式I/O:nonblockingIO
3.I/O复用(Select,pollepoll):IOmultiplexing
4.信号驱动式I/O(SIGIO):signaldrivenIO
5.异步I/O(posix的 aio系列函数):asynchromousIO
Blocking IO在Linux中,默认情况下所有的socket都是Blocking,一个典型的读操作流程大概是这样:
1.通常涉及等待数据从网络到达。当所有等待数据到达时,它被复制到内核中的某个缓冲区
2.把数据从内核缓冲区复制到应用程序缓冲区
当用户进程调用了 recvfrom这个系统调用, kernel就开始了IO的第一个阶段:准备数据。对于networkIO来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包)。这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。
所以,BlockingIO的特点就是在IO执行的两个阶段都被block了
Linux下,可以用过设置socket使其变为non-blocking。当对一个non-blockingsocket执行操作时,流程如下:
从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。 从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次 发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
所以,用户进程第一个阶段不是阻塞的,需要不断的主动询问kernel数据好了没有;第二个阶段依然总是阻塞的。
IO 多路复用(NIO)select、epoll的好处就在于单个process就可以同时处理多个网络链接的IO。
IO复用和同步阻塞本质一样,不过利用了新的Select系统调用,由内核来负责本来是请求进程该做的轮训操作,看似不非阻塞IO还多了哥系统调用开销,不过因为支持多路IO才算提高了效率
也就是一个可以监听多个。
它的基本原理就是select、epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如下图:
当用户线程调用select,那么整个进程会被阻塞,而同时,kernel会监视所有select负责的socket =,当任何一个socket中的数据准备好了,select就会返回,这个时候用户进程会调用read操作,将数据kernel拷贝到用户进程。
首先开启套接字的信号驱动式IO功能,并且通过sigaction(信号处理程序) 系统调用安装一个信号处理函数 ,该函数调用将立即返回,当前进程没有被阻塞 ,继续工作;当数据报准备好的时候,内核为该进程产生SIGIO 的信号,随后既可以在信号处理函数中调用recvfrom 读取数据报,并且通知主循环数据已经准备好等待处理;也可以直接通知主循环让它读取数据报;(其实就是一个待读取的通知和待处理的通知),基本不会用到。
多线程和多进程的模型虽然解决了并发的问题,但是系统不能无限的增加线程,由于系统的切换线程的开销恒大,所以,一旦线程数量过多,CPU的时间就花在线程的切换上,正真运行代码的时间就会减少,结果导致性能严重下降
由于我们要解决的问题是CPU高速执行能力和IO设备的龟速严重不匹配,多线程和多进程只是解决这一个问题的一种方法。
另一种解决IO问题的方法是异步IO,当代码需要执行一个耗时的IO操作时,他只发出IO指令,并不等待IO结果然后就去执行其他代码,一段时间后,当IO返回结果是,在通知CPU进行处理我们调用aio_read函数,给内核传递描述符,缓冲区指针,缓冲区大小,和文件偏移量,并且告诉内核当整个操作完成时如何通知我们,该函数调用后,立即返回,不会被阻塞
另一方面:从kernel的角度,当他收到一个aio_read之后,首先它立即返回,所以不会对用户进程产生block,然后kernel会等待数据准备完成,然后将数据拷贝到用户内存(copy由内核完成),当着一切完成后,kernel会给用户进程发送一个singal或者执行下一个基于线程回调函数来完成此次IO处理过程,告诉他read操作完成
美文佳句岁月应是静好。近来,心神总是不宁,想必是被尘世间的诱惑所困。
我想,要是远方的祥夫先生来到我这“梅知堂”,两人清茶一杯,盘腿而坐,或看他画梅,纸上的梅花仿佛兀自开在飞雪里,如是,那该是一幅怎样的墨梅图?
昨晚,梦里看到那个戴着小黑圆眼镜的祥夫背着黄色的大包正往江南赶路。是又到了梅花开的日子了吗?
面试题 SpringMVC工作原理?1.客户端发送请求到前端控制器DispatcherServlet
2.DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取handler
3.处理器映射器根据url找到具体的处理器,生成处理器对象以及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
4.DispatcherServlet调用HandlerAdapter处理器适配器
5.HandlerAdapter经过适配器调用具体处理器(Handler,也叫后端控制器)
6.Handler执行完成返回ModelAndView
7. HandlerAdaper将Handler执行结果ModelAndView返回给DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析
9.ViewResolver解析后返回具体View
10.DispatcherServlet对view进行渲染视图(即将模型数据填充至视图中)
11.DispatcherServlet响应用户
ArrayList 、LinkedList和Vector的区别?
@RestController 注解,在 @Controller 基础上,增加了 @ResponseBody 注解,更加适合目前前后端分离的架构下,提供 Restful API ,返回例如 JSON 数据格式。当然,返回什么样的数据格式,根据客户端的 "ACCEPT" 请求头来决定。
你好,我是yltrcc,日常分享技术点滴,欢迎关注我:ylcoder

