这个帐号已经注册一年多,但都是用来下载一些学习资料。今天发表第一篇文章,如有不足,欢迎批评指正。 package 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);// 改变此位置的值 } }