1.为什么要使用NIO
由于IO是基于阻塞IO模式的,读写操作都有可能会阻塞。如果用单线程处理IO,就会导致在线程阻塞时,整个系统都挂掉了。一个解决方案就是使用多线程,一个IO连接对应一个线程,而多线程又会引起几个问题:1.当有大量Http长连接时(如淘宝阿里旺旺),是不可能为每一个连接创建一个线程的。2.线程阻塞时会由用户态切换到核心态,保留线程上下文,这一过程的成本很高。 3.多线程通常会伴随着并发问题。
2.NIO与IO相比,优势在哪里
1)IO是面向流的,就导致他必须从流中读取一个或多个字节直到读取结束,因为他没有地方可以缓存;也不能移动流中前后的数据。
而NIO是面向缓冲区的,需要时可在缓冲区中前后移动,增加了处理过程中的灵活性。
2)IO是阻塞的,在等待读取或写入时,县城会阻塞等待,无法干别的事。
而NIO是非阻塞的,当一个通道发出请求进行读取数据时,他可以先读取现在可用的数据,如不存在可用的数据,他不会阻塞等待,会去做一些别的事情,比如其他通道的读写操作。写也是一样的。
3)NIO是基于Selector的,使我们能够只用一个线程就可以管理多个通道,通过将通道注册到selector上的方式。然后它是基于反应器模式的,当有事件来临时,会注册在selector中,然后selector会选取合适的通道处理事件。
3.NIO与AIO
都是异步的(指处理I/O事件与I/O处理的异步?)
NIO对于I/O事件是阻塞的(轮询),而对于I/O操作时不阻塞的。
AIO对于I/O事件与处理都是不阻塞的,不用等I/O时间真的发生就可以做别的事情。
4.NIO可能出现的问题
1)没有请求时CPU的占用率为100%
当注册了不感兴趣的事件时,又没有通道去处理,Selector.select()上就会始终有事件出现(并且没有I/O处理发生),CPU就一直处理了,而此时select()应该是阻塞的。
2)由于只使用了一个线程(多个线程也如此)处理用户请求,所以要避免线程被阻塞,解决方法是事件的处理者必须要即刻返回,不能陷入循环中,否则会影响其他用户的请求速度。
3)使用NIO != 高性能,当连接数<1000,并发程度不高或者局域网环境下NIO并没有显著的性能优势。
4)NIO并没有完全屏蔽平台差异,它仍然是基于各个操作系统的I/O系统实现的,差异仍然存在。使用NIO做网络编程构建事件驱动模型并不容易,陷阱重重。
可以使用成熟的NIO框架,如Netty,MINA等。解决了很多NIO的陷阱,并屏蔽了操作系统的差异,有较好的性能和编程模型。