随笔分类
IO模型
同步阻塞、同步非阻塞、多路复用、异步非阻塞
实际上,真正的数据读取得通过 os内核来完成,Java层面提供的 api实际上是去 请求系统调用
的!
当调用一次 channel.read或 stream.read后,会切换至 os内核态来完成真正数据的读取,而这个读取数据的过程又分为了 两个阶段
:
等待数据阶段
:等待客户端发送数据,客户端数据到达后,然后从网卡中被复制到内核的某个缓冲区
复制数据阶段
:把数据从内核缓冲区复制到进程缓冲区
《 Unix网络编程》一书中提及了五种 IO模型
:
-
阻塞 IO
发起一个请求,调用者一直等待请求结果返回,也就是说当前线程会被挂起,无法去干其它事,只有条件就绪时才从阻塞中出来,继续干活,cpu利用率低,线程略显 "死板"
阻塞 api之间会相互影响
这就好比我们去钓鱼,抛竿之后就一直在岸边等,等待鱼上钩,这期间啥也不做,大概在胡思乱想吧...
-
非阻塞 IO
发起一个请求,调用者不用一直等着结果返回 (如:没有数据也不会被阻塞),可以先去干其它事情
注:
数据复制阶段,用户线程还是被阻塞着的
;只是在数据就绪阶段,用户线程是非阻塞的,这点需要区分!这就好比钓鱼,抛竿入水后,就看下鱼漂是否有动静,如果没有鱼上钩,就去做些其他事,一会再来看看鱼漂是否有动静,即不断地进行轮询,看看有没有鱼上钩,有的话,自己来进行处理
-
多路复用 IO
通过一个 Selector来监听多个 Channel上是否有事件发生,有则去处理,没有的话线程阻塞
可以简单理解为 "事件驱动 IO - 个人理解"
这就好比钓鱼,雇了一个帮手,他可以来帮我们同时抛多个钓鱼竿,当有任何一杆的鱼上钩时,他就会通知我们,我们再来进行处理
-
信号驱动 IO
-
异步 IO
相对于同步 IO,异步 IO不是顺序执行的
异步:用户线程发起 IO后,可以去干其它事,这个过程是不阻塞的,IO请求返回后 (别的线程将数据赋值到用户空间去),此时通知用户线程,用户线程直接去拿数据即可
打个比方:去钓鱼,雇了个钓鱼高手,高手不仅擅长于钓鱼,且会在与上钩后通知我,那么我只需要委托他去抛竿,就能够去干其它事了,直到接收它的通知,我们再回来处理已经上岸的鱼,这个过程就是不阻塞的,即 "
异步
"注:
异步一定是非阻塞的
!而异步 IO之间,线程的协调实际上是通过一个
回调方法
来进行的 (用户线程在发送请求时会去定义一个回调,当其它线程完成数据的复制后,会去调用此回调,这就完成了线程间的协调)而前面所述的:阻塞 IO、非阻塞 IO、多路复用 IO,本质上都是
同步的
,因为发起请求和获取数据的过程都是由同一个线程
来完成,即亲力亲为