ackage com.jacp.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;
/**
* 对内存中文件加锁
* @author jacp
*
*/
public class MyFileLock {
private static final int BSIZE = 60;
private static FileChannel fc;
public static void main(String[] args) {
try {
fc = new RandomAccessFile("test.dat", "rw").getChannel();
MappedByteBuffer mapBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, BSIZE);
for(int i = 0; i < BSIZE; i++) {
mapBuffer.put((byte)'a');
}
// 三个线程分别修改不同的地方
mapBuffer.position(BSIZE/4);
mapBuffer.limit(2*BSIZE/3);
ByteBuffer buffer = mapBuffer.slice();
new LockAndModify(mapBuffer, 0, BSIZE/3);
new LockAndModify(mapBuffer, BSIZE/2, BSIZE);
while(buffer.hasRemaining()) {
modify(buffer);
}
Thread.sleep(1000);// 此处要延迟,不然看不到效果
mapBuffer.rewind();
System.out.println(mapBuffer.limit());
while(mapBuffer.hasRemaining()) {// 查看三个线程的修改效果
System.out.print((char)mapBuffer.get());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* capacity 为ByteBuffer的大小,在ByteBuffer创建时就被指定
* position 为当前读/写操作数据的下标位置
* limit 为ByteBuffer中有效数据的长度,在进行写操作时和capacity相等
* mark 一个临时存放的位置下标。调用mark()会将mark设为当前的position的值,
* 以后调用reset()会将position属性设置为mark的值。mark的值总是小于等于position的值,
* 如果将position的值设的比mark小,当前的mark值会被抛弃掉。
*
* Buffer clear()
* 把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用。
* Buffer flip()
* 把limit设为当前position,把position设为0,一般在从Buffer读出数据前调用。
* Buffer rewind()
* 把position设为0,limit不变,一般在把数据重写入Buffer前调用。
*/
private static class LockAndModify extends Thread {
private ByteBuffer buffer;
private int start;
private int end;
public LockAndModify(ByteBuffer buffer, int start, int end) {
buffer.limit(end);
buffer.position(start);
this.buffer = buffer.slice();// 创建新的缓冲区长度为end-start
this.start = start;
this.end = end;
start();
}
public void run() {
try {
FileLock fl = fc.lock(start, end, false);// 锁住文件的一部分
while(buffer.position() < buffer.limit()) {
modify(buffer);
}
fl.release();// 释放锁
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 修改byteBuffer中的值
* @param buffer
*/
public static void modify(ByteBuffer buffer) {
buffer.mark();// 记住此位置
byte b = (byte)(buffer.get()+1);// 读取一个,下标移动到后一位置
buffer.reset();// 将下标回到mark()位置
buffer.put(b);// 改变此位置的值
}
}
java nio 文件锁小例
最新推荐文章于 2025-08-07 15:29:44 发布