近期分享:BIO 与 NIO 的实质区别到底是什么?

作为一个 java 中年兵,每每遇到面试要准备的时候,都绕不开 BIO、NIO 这个话题。

最近又打开了一篇 NIO 文章,刚阅读前面部分的时候,突然想通了一些问题。想阅读原文的朋友可以vx文章里搜一下“NIO 概览”这个标题,是收集于 JavaGuide 公众号的一篇文章。

其在最开始提到:

NIO中的N可以理解为Non-blocking,不单纯是New。

它支持面向缓冲的,基于通道的I/O操作方法。

看到“缓冲”两个字,我觉得醍醐灌顶了,后面说的“基于管道”,我觉得只是基于英文API“Channel”的一个翻译而已。

BIO 和 NIO API之所以如此不同,全在于“缓存”的精髓上。

BIO,我们网上所查资料,都会千篇一律告诉你,它是基于“流”的。而这个“流”这个概念,是怎么出来的,可能因为都翻不到一手资料大家都略过不谈,而且 BIO 现存 API 数量和例子也较少,大家也不远深究了。

被虐千百遍后,再谈 BIO 的“流”和 NIO 的“管道”

现在我们知道,NIO 是面向缓冲的、基于通道的 I/O 操作方法。BIO 是面向“流”的。

NIO 为什么可以不用阻塞?原因在于可以缓存了。底层操作系统得到 I/O 数据包后可以存放到缓冲区中,不需要用户线程 CPU 一直等待。而且这种方式的便利之处是解放了单核 CPU 的多任务处理能力,可以同时处理多个缓冲区,也就是处理多个 IO 请求,而受到的 IO 之间的互相影响降到了最低。

BIO 为什么是阻塞的?这应该和 IO API 本身发展阶段密不可分。所有事物都可能要经历从简单到复杂的阶段。BIO 的操作原理,实现和理解起来简单得多。创造 BIO 时当时的 PC 条件可能就不怎么期望去处理多任务,最多也就几个或者十个任务,简单的起十条线程绑定处理就好了。或者从内存上考虑,如果要应用到缓存,势必会增加内存的用量。从如今编程界的一些经典算法和产品看,不可能在“远古时期”想不到“缓存”这个方案,而是实在是场景有限,不需要做到那么复杂,因此第一代 IO 就以 BIO 的面目产生了。

 

那,流 这个思想是怎么命名出来的呢?我说一下我的猜想。结合今天发现的 NIO 的特点,NIO 能缓存,数据在内存中留存的时间增加了。而 BIO 的“流”取水流之意,就好比一个水龙头,拧开水就倾泻而下,你把手放在水龙头下方,水龙头中的水会从第一滴到最后一滴从你手上快速的流过,要洗手就得趁这个时间赶快洗。NIO 对于这个水龙头来说,等于在下面接了个盆,你在盆中洗手,可以重复多次利用水资源,直到它“不干净”为止。

 

最后总结:不谈缓存的 NIO 介绍都是耍流氓

NIO 相比 BIO 的变化是加入了“缓存”。而顺手改了名的 API Channel(通道)等也是顺应了 API 的发展取的。如果不叫“通道”,它还可以叫别的,只是刚好大佬们写的时候用 Channel 而已。Channel 中文翻译还可以有多种,如 频道,渠道,方法,航道,海峡 等等,翻译的人取了一个“通道”作为意译。因此中文译法叫什么就不过多纠结了。

近期分享:BIO 与 NIO 的实质区别到底是什么?

上一篇:React中context的使用方法


下一篇:项目一文档