【java网络】五种IO模型

同步阻塞

特点:

在Linux中,对于一次读取IO的操作,数据并不会直接拷贝到程序的程序缓冲区,通常包括两个不同的阶段:

  • 等待数据准备好,到达内核缓冲区
  • 从内核向进程复制数据。对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所有等待分组到达使,它被复制到内核中某个缓冲区。第二步就是把数据从内核缓冲区复制到应用程序缓冲区

其实和生活联系起来,很容易理解;
小明从家里先到演唱会现场问售票业务员买票,但是票没有出来,三天后才出来,小明就在大厅中一直等待,知道票出来。

在这里插入图片描述

同步非阻塞

特点:
  • 非阻塞的recvform系统调用之后,进程并没有被阻塞,内核马上返回给进程消息,如果数据没有准备好,会返回一个error
  • 进程在收到error后,可以处理其他业务逻辑,过会再发起recvform系统调用。采用轮询的方式检查内核数据,直到数据准备好。
    之后拷贝数据到进程,进行数据处理。在Linux下,可以通过设置socke套接字选项使其变为非阻塞。

继续小明:小明从家里面先到演唱会现场问售票业务员买票,但是票还没出来,然后小明走了,办理其他业务,然后两小时过去了,又到举办商售票大厅买票,如果票还没有出来,再去干点别的,直到票出来在这里插入图片描述

I/O复用(事件驱动)

特点:
  • 优点:单个进程就可以同时处理多个网络连接的IO
  • 基本原理:不再由应用程序自己监视连接。取而代之由内核替应用程序监视文件描述符
    以select为例,当用户进程调用了select,那么整个进程会被阻塞,而同时,kernel会监视所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从内核拷贝到用户进程

再来小明:小明想买票看演唱会,直接给黄牛打电话,帮我留个票,票买了通知我,我自己去取(当我接到黄牛的电话时,我需要花费整个路程的时间去读这个数据,拿这个票)那么票还没还没出来前,小明还是可以干自己的事情。
在这里插入图片描述

信号I/O

特点:
  • 允许Socket进行信号驱动IO,并注册一个信号处理函数,进程继续运行并不阻塞。
  • 当数据准备好时,进程会受到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

继续小明:小明想买票看演唱会,给举办商售票业务员说,给你们留个电话,有票了请给我打个电话通知一下(因为售票员不提供代买票的机制),小明只能自己去买票(小明自己的的事情需要小明自己做)
在这里插入图片描述

异步非阻塞

特点:

上述四种IO模型都是同步的。相对于同步IO,异步IO不是顺序执行。

  • 用户进程进行aio_read系统调用之后,就可以去处理其他的逻辑了,无论内核数据是否准备好,都会直接返回给用户进程,不会对进程造成阻塞
  • 等到数据准备好了,内核直接复制数据到进程空间,然后从内核向进程发送通知,此时数据已经在用户空间了,可以对数据进行处理了。

在Linux中,通知的方式是“信号”,分为三种情况:

  1. 如果这个进程正在用户态处理其他逻辑,那就强行打断,调用事先注册的信号处理函数,这个函数可以决定何时以及如何处理这个异步任务。由于信号处理函数是突然闯进来的,因此跟中断跟中断处理
    跟中断处理程序一样,有很多事情是不能做的,因此保险起见,一般是把事件“登记”一下放进队列,然后返回该进程原来在做的事。
  2. 如果这个进程正在内核态处理,例如以同步阻塞方式读写磁盘,那就把这个通知挂起来了,等到内核态的事情忙完了,快要回到用户态的时候,再触出发信号通知
  3. 如果这个进程现在被挂起了,例如陷入睡眠,那就把这个进程唤醒,等到CPU调度,触发信号通知

继续小明:小明想买票看演唱会,给举办商售票业务员说(异步非阻塞i/o)打电话了,给你留个地址,有票了请通知快递员,把这张票送到这个地址来,当小明听到敲门声,看见快递员,就知道票好了,而且知道票好了的时候,票已经到他手上了,票不用小明自己去取(应用不用自己再去read数据了)。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值