文件映射通常应用于极大的文件,我们可能需要对这种巨大的文件进行部分加锁,以便其他进程可以修改文件中未被加锁的部分。例如:数据库就是这样,因此多个用户可以同时访问它。
看个例子:连个线程分别对文件的不同部分加锁:
package com.wjy.nio;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class LockingMappedFiles {
static final int LENGTH=0x8FFFFFF;
static FileChannel fc;
public static void main(String args[]){
try {
fc=new RandomAccessFile("./file/test.dat", "rw").getChannel();
MappedByteBuffer out=fc.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH);
for(int i=0;i<LENGTH;i++){
out.put((byte)'x');
}
new LockAndModify(out,0,0+LENGTH/3);
new LockAndModify(out,LENGTH/2,LENGTH/2+LENGTH/4);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static class LockAndModify extends Thread{
private ByteBuffer buff;
private int start,end;
LockAndModify(ByteBuffer mbb,int start,int end){
this.start=start;
this.end=end;
mbb.limit(end);
mbb.position(start);
buff=mbb.slice();
start();
}
public void run(){
try {
FileLock fl=fc.lock(start, end, false);
System.out.println("Locked: "+start+" to "+end);
while(buff.position()<buff.limit()-1){
buff.put((byte)(buff.get()+1));
}
fl.release();
System.out.println("Release: "+start+" to "+end);
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
注意这里是一个对缓冲区分片的操作:
mbb.limit(end); //设置尾部
mbb.position(start); //设置开头
buff=mbb.slice(); //分片