网络编程-BIO、NIO、AIO的原理与对比

什么是同步异步

同步和异步是针对应用程序和内核交互而言的。同步指的是用户进程触发IO操作并等待或者轮询查看IO操作是否就绪。而异步就是指用户进程触发IO操作后便开始干自己的事情,当IO操作完成后,用户会得到IO完成的通知。

举个栗子:

同步:自己去银行取钱。去了银行申请业务,等待叫号,处理完回家

异步:委托他人代为操作,自己可以干别的,等他人取完钱交给自己。

OS操作系统底层支持异步IO操作。


什么是阻塞和非阻塞

阻塞和非阻塞是针对远程访问数据的时候,根据IO操作的就绪状态采取的不同的方式。说白了就是一种读取或者写入操作函数实现方式。

阻塞方式下读取或者写入,行数将一直等待,而非阻塞方式下,读取或者写入函数会立刻返回一个状态值

举个栗子:

阻塞:ATM排队取款,你只能等待(使用阻塞IO时,Java会一直阻塞到读写完成才退出这个函数)

非阻塞:柜台取款,取号,然后坐在等待区椅子上,等待广播叫号通知你办理,没叫到你你就不能去。但是这个期间你可以不断地询问大堂经理排到你了没有。大堂经理会告诉你一个结果(使用非阻塞IO时,如果不能读写,Java调用会立刻返回。当IO事件分发器通知可以读写时,再继续进行读写,不断循环直到结束)

通过例子可以看出,你去取钱,自己去和不是自己去,跟去了使用ATM还是柜台办理,是没有任何关系的。也就是说阻塞非阻塞和同步异步并没有直接的关系。同步异步是使用多线程完成的,而阻塞非阻塞是这个线程需不需要等待前面的事务完成


BIO

同步阻塞编程方式。

就相当于你去银行办理业务,而且你使用了ATM取款机(只能自己处理事件,若服务端繁忙就会阻塞,等待服务端响应)

BIO编程方式通常是jdk1.4版本之前使用的编程方式。编程实现过程:首先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下ServerSocket会建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或遭到拒绝

大致结构如下:

在这里插入图片描述

服务端线程与客户端一一对应,处理客户端请求

可以通过线程池来优化BIO,避免高并发情况下服务端线程过多

客户端与服务端线程之间建立的链接属于长连接。长连接的特点就是数据可以多次往返。(HTTP协议通常是短连接,一个请求一个应答就会结束)

同步并阻塞: 服务器实现模式为:一个client链接一个server线程。即客户端有链接请求时服务器端就需要启动一个线程进行处理,如果这个链接什么事情也没干,就会造成不必要的线程开销。这一点可以通过线程池优化。

BIO适用于 链接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4前这是唯一的选择。但是程序直观简单容易理解。

使用线程池改善后的模型图如下:

在这里插入图片描述


NIO

同步非阻塞的编程方式。

就比如说,你去银行取钱,你选择叫号(同步非阻塞),你在叫号机上选择买烧饼,但是叫号机并没有这个选项,你就没法叫到号,也就没有柜台处理你买烧饼的业务(得不到服务器线程)。

NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题。NIO基于Reactor,当Socket有流可读或可写入socket时,操作系统会相应的通知应用程序进行处理,应用程序再将流读取到缓冲区或写入操作系统。也就是说,这个时候,不是说有一个链接就会有一个线程来处理,而是有效的请求,才会有线程处理。当一个链接没有数据时,是没有线程来处理的。

NIO的最重要的地方是当一个链接创建后,不需要对应一个线程,这个链接会被注册到多路复用器上面,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求,才开启一个线程处理请求。这个时候就进入了一个请求一个线程的模式。

在NIO中,当一个请求被线程处理时,可能会等待其他的资源比如数据库的资源,其实在等待数据库资源时这个线程就以及阻塞了。并发量很大的情况下还是可能会有BIO的问题,只不过这种情况就不说client链接中没有请求了,而且请求没法被及时的回应。
NIO模型如下

在这里插入图片描述

同步非阻塞: 实现模式为一个IO请求一个线程,客户端发送的所有链接都会被注册到多路复用器上,多路复用器轮询检查链接是否有I/O操作,有IO请求时才会启动一个线程进行处理。

NIO模式适用于 连接数目多,且链接操作比较轻的架构,比如聊天服务器。并发局限于应用中,编程复杂,JDK1.4开始支持

AIO

异步非阻塞编程方式

在JDK1.7引入相关概念

与NIO不同,当进行读写操作时,只需调用API的read和write方法即可。这两种方法均为异步操作。对于读操作而言,当有流可以进行读取时,操作系统会将可读的流传入Read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。也就是说read和write方法都是异步的,完成后会主动调用回调函数。在JDK1.7中,这个部分的内容被称作NIO.2。主要在Java.nio.channels包下增加了四个异步通道:

   AsynchronousSocketChannel

   AsynchronousServerSocketChannel

   AsynchronousFileChannel

   AsynchronousDatagramChannel

异步非阻塞: 服务器实现模式为一个有效请求一个线程,客户端的IO都是由OS操作系统完成的,再通知服务器取启动线程进行处理。

AIO方式适用于链接数目较多且操作较重的架构,比如QQ空间相册的那种感觉的,充分调用OS参与并发操作,编程复杂,从JDK1.7开始支持

参考视频链接
https://www.bilibili.com/video/BV1mE411d7nb?p=1
众所周知,B站是用来学习的在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值