目的:Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据。
通道与操作系统的文件描述符和文件句柄有着一对一的关系。
缓冲区是通道内部用来发送和接收数据的端点
InterruptibleChannel是一个标记接口,当通道使用时可以标示该通道是可以中断的。
通道只能在字节缓冲区上操作。
描述通道行为的接口都是在java.nio.channels包中定义的,不过具体的通道实现却都是从java.nio,channels.spi包中定义的。
SPI包允许新通道实现以一种受控且模块化的方式被植入到java虚拟机上。
I/O可以分为广义的两大类别:File I/O和Stream I/O。对应文件和套接字。
FileChannel对象只能通过一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel()方法来获取。不能直接创建FileChannle对象。
通道不能重复利用
如果一个线程在一个通道上被阻塞并且同时被中断(由调用该被阻塞线程的interrupt()方法的另一个线程中断),那么该通道将被关闭,该被阻塞线程也会产生一个ClosedByInterruptException异常。
假如一个线程的中断状态被设置,并且该线程试图访问一个通道,那么这个通道将立即被关闭,同时抛出ClosedByInterruptException异常。
线程中断状态通过调用Thread.interrupted()方法清除。
可以中断的通道也是可以异步关闭的。实现InterruptibleChannel接口的通道可以在任何时候被关闭。当 通道被关闭时,休眠在该通道上的所有线程都将被唤醒并收到一个AsynchronousCloseException异常。
Scatter/Ganther指在多个缓冲区上实现一个简单的I/O操作。顺序抽取write的gather.
FileChannel类可以实现常用的read,write以及scatter/gather操作
文件通道总是阻塞式的,本地磁盘I/O延时很少。
FileChannel对象是线程安全的,多个进程可以在同一个实例上并发调用方法而不会引起任何问题。
FileChannel类保证同一个jvm上所有 实例看到的某个文件的视图均是一致的。
FileChannel | RandomAccessFile |
read() | read() |
write() | write() |
size() | length() |
position() | getFilePointer() |
position(long new position) | seek() |
truncate | setLength |
force | getFD().sync() |
新的FileChannel类提供了一个名为map()的方法,该方法可以在一个打开的文件和一个特殊类型的ByteBuffer之间建立一个虚拟内存映射。
FileChannel在调用map()方法会创建一个由磁盘文件支持的虚拟内存映射,并在那块虚拟内存空间外部封装一个MappedByteBuffer对象。
通过内存映射机制来访问一个文件会比使用常规方法读写高效得多,甚至比使用通道的效率都高。原因是不需要做明确的系统调用。
MappedByteBuffer对象的数据元素存储在磁盘上的一个文件中。
buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,100,200);
映射整个文件
buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,0,fileChannel.size());
MapMode.READ_ONLY只读,MapMode.WRITE_ONLY可写,MapMode.PRIVATE私有,改映射但不改文件。
一旦映射建立之后将保持有效,直到MappedByteBuffer对象被垃圾收集为止。
MemoryMappedBuffer直接反映它所关联的磁盘文件。它有固定大小。如果映射文件大小变化,那么缓冲区的部分或全部内容都可能无法访问,并将返回未定义的数据或抛出未检查的异常。
public abstract class MappedByteBuffer extends ByteBuffer{
public final MappedByteBuffer load();
public final boolean isLoaded();
public final MappedByteBuffer force();
}
FileChannel的传输channel-to-channel两方法transferFrom,transferTo