Java NIO笔记 Channel

Plux posted @ 2012年6月29日 23:49 in Java with tags java java nio , 4010 阅读

记得第一次做计算机网络的实验课的时候,我用多线程实现了一个HTTP服务器,然后对能够同时对应多个客户端的读请求十分满意。没想过线程的开销问题。不过,后来在手机端设计一个需要同步读写的服务器的时候,才突然发现,要实现维护多个线程的同时,同步读写并不是那么容易的事情。

文中有什么问题,希望指出完善。:-)

而Java发布1.4版本的时候,就已经引入了新的NIO库,带来了非阻塞的更高性能的实现。但是,为什么新的java.nio包没有完全取代旧的java.io包,而在java.io包里反而嵌入java.nio包的内容呢?

NIO的封装

Java程序员很喜欢封装,把一个问题封装到更小的问题里,然后着手解决。所以,Java的世界里出现了很多框架,它们把重复劳动都封装好了,只提供了差异部分的代码接口。因此,用Java写代码的难处是,你找到了一个看起来可用的框架/封装,但只有在你了解这个框架/封装的设计思想,然后,你才能顺利解决一个问题。NIO就是这种情况。

Java NIO相对于旧的java.io库来说,并不是要取代,而是提出的三个新的设计思路:

  • 对原始类型的读/写缓冲的封装
  • 基于Channel的读写机制,对Stream的进一步抽象。
  • 事件轮询/反应设计模式(即Selector机制)

按上述思路,而Channel机制是作为Stream的进一步抽象而产生的,那么Channel和Stream相比有什么不同呢?按字面理解实际上就可以获得信息:Stream作为流是有方向的,而Channel则只是通道,并没有指明方向。因此,读写操作都可以在同一个Channel里实现。Channel的命名强调了nio中数据输入输出对象的通用性,为非阻塞的实现提供基础。

在Channel的实现里,也存在只读通道和只写通道,这两种通道实际上抽象了Channel的读写行为。

至于Channel的IO阻塞状态读写,则和传统的java.io包类似。但多了一层缓冲而已。因此,按照原来的设计思路来用nio也是可行的,不过nio的设计本质上我觉得还是非阻塞输入输出控制,把控制权重新交给程序员。

因此,java.nio从设计角度看,就不是替代java.io包,而是为java.io提供更多的控制选择。

Channel和Buffer的关系

Buffer的作用主要体现在Channel的非阻塞状态下。Channel如果不是阻塞的,那么每次调用必须立即返回,那样,读写操作都不至于影响对方。那么,立即返回意味着能够读写多少数据呢?这是不确定的,依赖于当前的传输状况。因此,作为缓冲的Buffer就为信息的完整性提供一个保障。每次读写操作都先把数据放到Buffer里面,然后多次调用Channel的读写方法对数据进行操作,依靠对Buffer的状态来判断数据的完整性。

更多内容

由于现在所学内容繁多,对Java NIO的学习也只是在空闲时间里进行,共享的学习笔记,有错希望大家能指出,也希望分享的笔记对同样在学习NIO内容的人有帮助。更详细的内容,参考两篇来自IBM DeveloperWork的文章:

前一篇文章是从服务器设计的角度来看NIO的非阻塞性能的;而后一篇文章,则详细地介绍了NIO的基本设计思路。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter