channel java_JavaNIO中的Channel概述

前面一些Java的文章已经简要对Java NIO做了描述,也详细地介绍了NIO中最基本的Buffer。这篇文章将继续介绍NIO的第二个主要角色 —— Channel。Channel

是对数据的源头和数据目标点流经途径的抽象,在这个意义上和InputStream和OutputStream类似。Channel可以译为“通道、管

道”,而传输中的数据仿佛就像是在其中流淌的水。前面也提到了Buffer,Buffer和Channel相互配合使用,才是Java的NIO。

0. Channel简述

“A nexus for I/O operations.”这是Java API中对Channel的描述,说的是Channel是IO操作的连接点。

开门见山,既然Channel是Java NIO中这么重要的一个角色,那么我们来看一下Java API中给出的类结构图。

49582994_1.jpg

Channel类层次结构(摘自《Java NIO》)

从上至下,前三层是描述和约定Channel功能的interface(除了java.nio.channels.spi. AbstractInterruptibleChannel),而在下面几层是和这些结构对应的Channel类。

图中也给出了各个interface和class的方法。Channel接口本身只是总体上提供了两个“不痛不痒”的方法。而紧接着的下面三个接口,各为自己的特征给出了一个方法约定。第三层的接口则是更进一步更具体的扩展。

再往下看,就是实现这些接口的类,从图中左右两侧可以看到,实际上是分为了两大类。一类是SelectableChannel,而另一类是FileChannel。而SelectableChannel实际上是网络通信相关的SocketChannel等的实现基础。

需要注意的是,图中下层的这些class实际上也都是abstract的,即抽象类。我们上面也说过,Channel是数据源和数据归宿之间通道的

抽象。而实际的IO必然是和底层操作系统相关的,是需要依赖平台的具体实现,这些不会再高度抽象的跨平台Java

API中体现,只是在JDK实现中有所不同。

除图中提到的以外,还有提供静态方法的工具类Channels。另外,后续的JDK1.7中页增加了新的内容。

1. Channel的使用和分类

之前在介绍ByteBuffer的时候就已经提到过了,Channel是同系统底层数据的交互,为了保证效率,统一使用字节为单位。从上面的类层次

结构图中也可以看得出来,Channel的两个子接口分别是ReadableByteChannel和WritableByteChannel,而

ByteChannel则对这两个接口做了合并归纳。而且SocketChannel和FileChannel都实现了这些接口。

需要注意的是,随着Java API的发展变化,接口的继承关系也和上图绘制的有所不同。如在JavaSE7中,增加了SeekableByteChannel接口等。尽管如此,大体上还是维持了原来的设计结构。

关于Channel对象的创建,有两类情况。对于Socket相关的Channel,只要调用特定类的open()方法即可,之后进行bind或者

connect操作。而文件相关的FileChannel则不然,需要通过FileInputStream、FileOutputStream或者

RandomAccessFile的getChannel()获取Channel对象。

从这个地方,我们就发现,其实Channel根据IO服务的情况主要分为两大类,按照《Java NIO》的描述,两类IO分别是:file

I/O 和 stream

I/O。前者是针对文件读写操作的,而后者多是网络通信相关的和Socket相关的。Channel分类也基本如此,和前者对应的

FileChannel,以及与后者对应的SocketChannel等类对象。

两者的区别不仅仅在Channel对象的构建和初始化上,更重要的还是和Selecotor的结合使用相关。也包括是否支持阻塞模式等。

接下来就是通过Channel进行实际的IO操作,即读和写。其实,这两项分别都在ReadableByteChannel和WritableByteChannel中声明了的。ByteChannel的子类都有

这两个方法。

需要注意的是,尽管你所拿到的Channel对象都是有read()和write()方法的,但并不代表他们一定是可读或者可写的。是否可以读写需要了解这个Channel的来头,这是比较讨厌的一点。

读写之后,通常就要进行关闭操作。关闭的概念其实很简单,当一个Channel被关闭后,就不再可用。相关的close()和isOpen()方法

可以进行关闭和检查Channel是否是打开状态。执行close()可能会对线程造成阻塞,当一个Channel关闭后,后续的close()操作直接

返回。

当Channel对象的close和中断结合起来,就有些要提到的了。一个阻塞在Channel对象上的线程如果收到了中断操作,则Channel

对象关闭,线程收到ClosedByInterruptException异常。而把顺序稍微调整一下,一个已经被set中断信号的线程访问

Channel对象时,Channel对象也会被关闭,线程得到ClosedByInterruptException异常。其它阻塞在这个

Channel上的线程会得到AsynchronousCloseException异常。

以上这段中提到的Channel对象需要InterruptibleChannel接口,但FileChannel和SocketChannel等大多数类都完成了对这个interface的实现。

2. Scatter/Gather集与散

Scatter的意思是分散,Gather的意思是聚集。我们注意到在上面的类层次结构图中,除了ByteChannel外,各Channel类还都实现了两个接口,分别是:

ScatteringByteChannel

GatheringByteChannel

对于这两个接口,这里不做过多描述。也许我们通过接口中约定的方法,就大概知道他们的作用了。

实际上就是对读写操作进行顺序多Buffer的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值