首页 > 编程学习 > 理解BIO/NIO的基本模型

理解BIO/NIO的基本模型

发布时间:2022/1/17 12:25:46

名称的理解

BIO(Block-IO):(同步)阻塞IO

NIO(No-Block IO): (同步)非阻塞IO

AIO(asynch IO):异步(非阻塞)IO

从标题中我们可以看出主要差异点是:阻塞/非阻塞、同步/异步 , 理解这个问题的核心主要就在于理解:阻塞与非阻塞、同步与异步的差异究竟是什么。

PS:看的时候带着问题思考下,为什么没有ANIO(异步阻塞IO)?

阻塞与非阻塞

首先,我们先下个概述定义,阻塞非阻塞说的是线程的状态。

我们先从代码上看看关键的Blokc点,当我们申明ServerSoket并调用accept();方法后,由于这个Soket是运行在主线程中,这个accept后主线程会Block在这个地方{当然,如果你是New Thread来run ServerSoket 会阻塞这个新建的Tread,阻塞的运行线程。注意区分:BIO并不意味着单线程},等待Client的输入才会继续往下执行。

我们换一个理解方式,对整个信息网络理解为一个高速路+收费站的模型。

高速路上的车 == 来自客户端的数据

高速路收费站的work  ==  serverSocket ,并且在这里只有一个高速路收费员。这种情况下收费员 = 主线程 。

阻塞模型下,相当于:这个收费员一旦上班,他就只能做一件事,就是在收费亭等着车辆来,然后收费放行。在没有车来的时候,收费员就一直坐着等,不会处理其他事情。

我们总结一下:在BIO里面, 收费员(主线程)只能干一件事情收费,如果没有车(数据)的输入,收费员(主线程)会一直Blokc,等待输入。所以,这个线程就阻塞了。

那么什么是非阻塞呢,在非阻塞里面,我们引入了一个 缓冲区 + Selector的概念,是什么意思呢。我们还是以高速路为例,相当于,在收费站之前,我们增加了一个停车场(缓冲区),并且在停车场内我们设置了一个调度员(Selector)。

这样,我们来看下模型下我们如何工作呢。

  1. 一旦有数据进来,先找调度员登记,登记完后把数据放入缓存区
  2. 收费员每隔一段时间来问一下调度员,有没有数据要处理,如果有就处理掉,如果没有,就继续去干其他的时期。

这样,我们的收费员(主线程),就没有Block ,如果没有数据进来,他不用一直等着,可以随时去干别的事情。

在阻塞与非阻塞的理解里面我们主要有几个关键对象要掌握:

车 =  网络中传输的数据

收费员 = server的主线程

调度员 = selector

停车场 = 数据缓冲区

真正block 与 no-block主要是针对 收费员的(即:主线程) , 调度员与停车场,都是实现,no-block 收费员的手段。

我们还是来看下关键代码是怎么实现的,注意看注释:

看到这里,是否已经明白什么是 阻塞 与 非阻塞了 ,其实关键就是,是否阻塞了 收费员(主线程), 如果还不是特别清楚,建议: 运行下BIO的demo,观察下Accept后主线程是不是就停在那里了。

PS:大家注意一下,这个只是对 阻塞与非阻塞的讲解, 并不完全等同于java中的NIO,JAVA的NIO在这个基础上有更多的优化. 比如:我们在看网络上的其他NIO文章时,经常会看到:

IO的多路复用:简单点理解,其实就是高速路不是一个条道,而是4车道、8车道,然后每条车道都带一个selector调度员。

Epoll模型:其实就是对selector的优化,我们现有模型下,是收费员定期来问调度员是否有数据需要处理。每次轮询也是消耗资源的,如果轮询结果是没有数据需要处理,这个轮询就浪费了(尤其是在程序中,由于执行速度快,空轮询其实消耗资源蛮大)。Epoll 就是改了一下,有数据需要处理时,有selector 主动通知,收费员。避免空轮询。

带着这些理解,再去看网上的其他介绍,BIO 、NIO的文章 应该更能理解。

讲到这里,我们发现篇幅已经很多,下次再开个单章讲什么是 同步与异步。

Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000