前言:
Buffer、Channel、Selector,NIO三大件。之前的博客中我们介绍了Buffer的一系列知识。从本篇开始,笔者将会介绍下Channel相关的知识。
1.Channel基本定义
Channel,翻译过来就是通道。通道表示打开到IO设备(文件、套接字)的连接。
通道有点类似于流的概念,就是InputStream和OutputStream,都是可以用来传输数据的。但是两者之间又有本质的不同,不同点如下:
* 通过通道,程序既可以读数据又可以写数据;流的读写则是单向的(比如InputStream就是读,OutputStream就是写)
* 通道可以进行数据的异步读写;而流的读写一般都是阻塞的同步的;
* 通道的数据读写需要通过Buffer,Buffer的操作比较灵活;而流的话直接读写在byte[]中;
2.Channel的类图
我们从几个层级来展示下Channel由上至下的接口实现
2.1 Channel接口

public interface Channel extends Closeable {
// 当前通道是否打开
public boolean isOpen();
// 关闭通道
public void close() throws IOException;
}
一个打开的通道即代表是一个特定的IO服务的特定连接。
当通道关闭后,该连接会丢失。对于已经关闭的通道进行读写操作都会抛出ClosedChannelException。
调用close方法来关闭通道时,可能会导致通道在关闭底层的IO服务的过程中线程暂时阻塞。通道关闭的阻塞行为取决于操作系统或对应文件系统。
2.2 InterruptibleChannel
只是一个标记接口,表示当前通道是可被中断的。
实现该接口的通道有以下特性:如果一个线程在一个通道上被阻塞并且同时被中断,那么当前通道则会被关闭,同时该阻塞线程也会产生一个ClosedByInterruptException。
2.3 ReadableByteChannel和WritableByteChannel
// WritableByteChannel.java
public interface WritableByteChannel extends Channel {
public int write(ByteBuffer src) throws IOException;
}
// ReadableByteChannel.java
public interface ReadableByteChannel extends Channel {
public int read(ByteBuffer dst) throws IOException;
}
可以看到,这两个就是新增了对ByteBuffer的read和write操作
2.4 ByteChannelpublic interface ByteChannel
extends ReadableByteChannel, WritableByteChannel
{
}
只实现其中一个接口(ReadableByteChannel或WritableByteChannel)则只能实现单向的读或写,数据只能在一个方向上传输。
ByteChannel继承了ReadableByteChannel和WritableByteChannel,
实现ByteChannel的类可以同时进行读和写,实现数据的双向传输。
2.5 SelectableChannel及其实现类/** A channel that can be multiplexed via a {@link Selector}. */
public abstract class SelectableChannel
extends AbstractInterruptibleChannel
implements Channel
{
public abstract SelectorProvider provider();
public abstract SelectionKey keyFor(Selector sel);
public abstract SelectionKey register(Selector sel, int ops, Object att)
throws ClosedChannelException;
...
}
可以看到,SelectableChannel不再是单打独斗的Channel了,而是与Selector进行了结合。
从它的注释中我们能看到,这种Channel是一种通过Selector进行多路复用的Channel。
看其的实现类SocketChannel、ServerSocketChannel,我们也知道,这些都是使用多路复用的最佳场景。
2.6 FileChannel
/** A channel for reading, writing, mapping, and manipulating a file. */
public abstract class FileChannel
extends AbstractInterruptibleChannel
implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel
{
...
}
FileChannel看其注释,就会了解到,这是一个操作文件的Channel。我们通过FileChannel可以读、写、mapping(映射)、操作一个文件。
总结:
从最终实现上来看,我们可以将IO简单分为两大类:File IO和Socket Stream IO,分别用于操作文件和网络套接字。
后续的文章中,我们也按照这个大方向,先介绍File IO相关操作,后续再介绍Socket Stream IO相关操作。