JavaNIO-文件通道
文件通道,是一种特殊的通道。
对于文件通道来说,是不能阻塞的。所以并不能设置非阻塞模式。
对于异步文件I/O来说,这是很多操作系统支持的,NIO也会增强。
一个FileChannel只能从RandomAccessFile,FileInputStream和FileOutputStream来获取(getChannel),然后你就获得了某种能力,请看:
package java.nio.channels; public abstract class FileChannel extends AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel { // This is a partial API listing// All methods listed here can throw java.io.IOException public abstract int read (ByteBuffer dst, long position) public abstract int write (ByteBuffer src, long position) public abstract long size( )public abstract long position( ) public abstract void position (long newPosition)public abstract void truncate (long size) public abstract void force (boolean metaData) public final FileLock lock( )public abstract FileLock lock (long position, long size, boolean shared) public final FileLock tryLock( ) public abstract FileLock tryLock (long position, long size, boolean shared) public abstract MappedByteBuffer map (MapMode mode, long position, long size) public static class MapMode { public static final MapMode READ_ONLYpublic static final MapMode READ_WRITE public static final MapMode PRIVATE }public abstract long transferTo (long position, long count, WritableByteChannel target) public abstract long transferFrom (ReadableByteChannel src, long position, long count)}
以上的操作,都会抛出java.io.IOException
FileChannel对象是线程安全的,但是注意的是,影响到通道位置和文件大小的操作是单线程的。
对于同一个虚拟机,我们看到的对于某一个文件的FileChannel实例视图都是一致的。
FileChannel对于的操作和POSIX中的一些API函数很相像。
public abstract class FileChannel extends AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel { // This is a partial API listing public final FileLock lock( )public abstract FileLock lock (long position, long size, boolean shared) public final FileLock tryLock( ) public abstract FileLock tryLock (long position, long size, boolean shared) }
我们可以看到,lock可以锁住一个文件的某个区域。而且这个区域可以使比文件还大。
超出文件尾的。这样,新写入的内容也被锁住。使用lock可能会阻塞,等待前一个lock被释放。
tryLock和lock一样。只是如果当时没有可用锁,就立即返回一个null,而不是阻塞。
FileLock 类如下:
public abstract class FileLock {public final FileChannel channel( )public final long position( ) public final long size( ) public final boolean isShared( ) public final boolean overlaps (long position, long size) public abstract boolean isValid( ); public abstract void release( ) throws IOException; }
一旦FileLock对象创建就生效。注意,创建以后,position,是否独占,大小就不能改变了。
FileLock是线程安全的,可以多个线程同时访问一个锁。注意,在你不确定操作系统是否支持独占性时,使用isShared()来判断是否该锁支持共享。
如果你要查看一个感兴趣的区域是否与当前的锁有冲突,可以使用 overlaps,这个函数返回的是当前进程上的,即使是返回为false,也不一定可以获取到FileLock。
最后,使用文件锁,一定要释放。使用try...catch...finally
FileLock lock = fileChannel.lock( ) try { <perform read/write/whatever on channel> } catch (IOException) [ <handle unexpected exception> } finally {lock.release( )}
注意,FileLock是针对不同进程的。如果在一个进程内,锁是无意义的。