转自:http://www.molotang.com/articles/894.html
在Java发布JDK1.4之后,NIO也随之出现了。NIO的出现实际上是为了给Java开发提供更多更多更灵活的接口,当然也是为了提高性能。我们本篇对NIO做一个概述。
0. IO的同步异步和阻塞
Java NIO就是Java New IO。但NIO也通常会和BIO和AIO放在一起来提,有人把NIO理解为non-blocking IO,即非阻塞IO。这个理解其实也是有道理的,因为NIO使得非阻塞IO成为了可能。我们这里就对IO的同步异步和阻塞非阻塞简单整理下,这实际上是对IO分类的两个维度。
阻塞和非阻塞,这个很好理解。阻塞就是当线程发起IO请求后线程阻塞,直到IO操作完成后线程再恢复执行。非阻塞就是发起请求,如果没有结果也不需要等待,直接返回。
同步和异步有很多解释。
一种说法,同步异步是指有状态依赖,同步一般是指做完一件事情之后再做另一件事情,也就是说做第二件事情之前要等待第一件事情完成。而异步则可以不考虑这些直接去做别的事情。
也有一种说法是通信的方式,由谁来负责通知IO的实际完成事件。
http://www.zhihu.com/question/19732473
Java传统的字节流字符流IO大部分都是BIO,即阻塞IO。而在NIO中,Channel则可以使用非阻塞式的IO请求。在JavaSE 7中,又增加了一些AIO的特性。
1. Java API中的NIO
我们看下Java API中NIO的包。
java.nio包中主要是包含了NIO的Buffer的概念定义。而java.nio.channels包中则主要是Channel概念相关类的定义,Selector的概念也定义在这个包中。这三者是Java NIO的主要角色,除此之外Java NIO也定义了其它子包。其中很多地方都用到了SPI,即Service Provider Interface的概念定义了子包。
除此之外,Java NIO中还包含了字符集Charset、正则表达式和文件处理相关的内容。
2. IO复用
按我的理解,JavaNIO最吸引人的还是IO复用的特性。
在NIO之前,通常一个Java的服务器接到很多客户端的连接请求,而为每一个请求都开辟了一个线程做请求处理。而随着异步请求和长连接的流行,很多时候,一个连接虽然一直处于保持状态,但数据请求很少,不需要很多资源对请求进行持续处理。而之前每一个连接一个线程的模式就会浪费服务器资源,因为线程是需要占用资源的。
更为合适的一种方式是,连接可以一直维持,但处理请求的线程拿来复用,即一个线程处理多个连接比较分散的请求。这就是我们要说的IO复用。
在NIO中,每一个数据连接都可以对应为一个Channel,而我么可以把针对某个Channel的特定感兴趣的事件注册到Selector上,处理请求的线程只要检测Selector的状态就好。当Selector收到特定的事件时,我们的执行线程可以通过这个Selector获取相关的Channel,进行相应的处理工作。此后继续检查Selector。这样一个线程就可以复用,来处理不同Channel上的数据请求。
参考:
http://docs.oracle.com/javase/1.4.2/docs/guide/nio/
作者原创,难免有错误,欢迎读者热心评论留言指出,以免误导他人,谢谢!