background image

Java NIO 类库 Selector 机制解析

一、  前言

 
自从 J2SE 1.4 版本以来,JDK 发布了全新的 I/O 类库,简称 NIO,其不但引入了全新的
高效的 I/O 机制,同时,也引入了多路复用的异步模式。NIO 的包中主要包含了这样几种
抽象数据类型:
 

Buffer:包含数据且用于读写的线形表结构。其中还提供了一个特殊类用于内存映射

文件的 I/O 操作。 

Charset:它提供 Unicode 字符串影射到字节序列以及逆映射的操作。 

Channels:包含 socket,file 和 pipe 三种管道,都是全双工的通道。 

Selector:多个异步 I/O 操作集中到一个或多个线程中(可以被看成是 Unix 中

select()函数的面向对象版本)。 

 
我的大学同学赵锟在使用 NIO 类库书写相关网络程序的时候,发现了一些 Java 异常
RuntimeException,异常的报错信息让他开始了对 NIO 的 Selector 进行了一些调查。
当赵锟对我共享了 Selector 的一些底层机制的猜想和调查时候,我们觉得这是一件很有
意思的事情,于是在伙同赵锟进行过一系列的调查后,我俩发现了很多有趣的事情,于
是导致了这篇文章的产生。这也是为什么本文的作者署名为我们两人的原因。
 
先要说明的一点是,赵锟和我本质上都是出身于 Unix/Linux/C/C++的开发人员,对于
Java,这并不是我们的长处,这篇文章本质上出于对 Java 的 Selector 的好奇,因为从
表面上来看 Selector 似乎做到了一些让我们这些 C/C++出身的人比较惊奇的事情。
 
下面让我来为你讲述一下这段故事。
 

二、  

 

故事开始 : 让 C++程序员写 Java 程序!

 
没有严重内存问题,大量丰富的 SDK 类库,超容易的跨平台,除了在性能上有些微辞,
C++出身的程序员从来都不会觉得 Java 是一件很困难的事情。当然,对于长期习惯于使
用操作系统 API(系统调用 System Call)的 C/C++程序来说,面对 Java

中的比较 另

类 地操作系统资源的方法可能会略感困惑,但万变不离其宗,只需要对面向对象的设计
模式有一定的了解,用不了多长时间,Java 的 SDK 类库也能玩得随心所欲。
 
在使用 Java 进行相关网络程序的的设计时,出身 C/C++的人,首先想到的框架就是多
路复用,想到多路复用,Unix/Linux 下马上就能让从想到 select, poll, epoll 系统调用。
于是,在看到 Java 的 NIO 中的 Selector 类时必然会倍感亲切。稍加查阅一下 SDK 手册
以及相关例程,不一会儿,一个多路复用的框架便呈现出来,随手做个单元测试,没啥
问题,一切和 C/C++照旧。然后告诉兄弟们,框架搞定,以后咱们就在 Windows 上开
发及单元测试,完成后到运行环境 Unix 上集成测试。心中并暗自念到,跨平台就好啊,
开发活动都可以跨平台了。