首页 > 技术文章 > NIO随笔

yan-zm 2020-01-20 15:50 原文

NIO是自JDK1.4后引入的新API,全名为Non-Block IO,也可以理解为新IO。

它为所有的原始类型(boolean类型除外)提缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。

与传统IO相比,NIO采用了异步非阻塞的机制,可以更高效地处理IO事件和减少线程节省服务器开销,而传统IO 是面向流的、阻塞的

 

 

NIO与BIO的区别

BIO:全称是Block IO,即阻塞型IO,在IO数据传输的过程中,数据通道是出于阻塞状态,一般可分为两种:1、调用read从socket里读取一段数据 2、调用read从一个磁盘文件读取一段数据到内存;对于第一种情况,可以算是Block,通道socket没有数据过来,对于read程序来说,只能一直等着,而第二种情况,严格上不算阻塞,因为从磁盘文件读取数据,是明确的点对点传输,它是占用了传输通道,但并不能称之为阻塞;

网络服务为了同时响应多个并发的网络请求,必须实现为多线程的。每个线程处理一个网络请求。线程数随着并发连接数线性增长。这的确能奏效。实际上2000年之前很多网络服务器就是这么实现的。但这带来两个问题:
1、线程越多,上下文切换就越多,而上下文切换是一个比较重的操作,会无谓浪费大量的CPU 2、每个线程会占用一定的内存作为线程的栈。比如有1000个线程同时运行,每个占用1MB内存,就占用了1个G的内存。但是水涨船高,并发量上去了还是吃不消;
因此,需要在操作IO接口的时候,操作系统能够明确地告诉程序有没有数据,而不是Block干等,于是NIO出现了;

NIO:NIO是指将IO模式设为“Non-Blocking”模式;在Block模式下,数据没有到达会一直等待,而NIO在这种情况下会返回-1,并过一段时间再进行尝试;这比之前BIO好多了,起码程序不会被卡死了。

但这样会带来两个新问题:1、如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的上下文切换(read是系统调用,每调用一次就得在用户态和核心态切换一次)2、休息一会的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已。要是操作系统能一口气告诉程序,哪些数据到了就好了。
于是IO多路复用被搞出来解决这个问题。

IO多路复用:IO多路复用(IO Multiplexing) 是这么一种机制:程序注册一组socket文件描述符给操作系统,表示“我要监视这些流是否有IO事件发生,有了就告诉程序处理”。IO多路复用和NIO是要配合一起使用才有实际意义

推荐阅读