Java nio 文件锁一例


Java nio 文件锁一例“:

  1. package com.jacp.nio;   
  2. import java.io.FileNotFoundException;   
  3. import java.io.IOException;   
  4. import java.io.RandomAccessFile;   
  5. import java.nio.ByteBuffer;   
  6. import java.nio.MappedByteBuffer;   
  7. import java.nio.channels.FileChannel;   
  8. import java.nio.channels.FileLock;   
  9. /**  
  10.  * 对内存中文件加锁  
  11.  * @author jacp  
  12.  *  
  13.  */  
  14. public class MyFileLock {   
  15.     private static final int BSIZE = 60;   
  16.     private static FileChannel fc;   
  17.     public static void main(String[] args) {   
  18.         try {   
  19.             fc = new RandomAccessFile("test.dat""rw").getChannel();   
  20.             MappedByteBuffer mapBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, BSIZE);   
  21.             for(int i = 0; i < BSIZE; i++) {   
  22.                 mapBuffer.put((byte)'a');   
  23.             }   
  24.                
  25.             // 三个线程分别修改不同的地方    
  26.             mapBuffer.position(BSIZE/4);   
  27.             mapBuffer.limit(2*BSIZE/3);   
  28.             ByteBuffer buffer = mapBuffer.slice();   
  29.             new LockAndModify(mapBuffer, 0, BSIZE/3);   
  30.             new LockAndModify(mapBuffer, BSIZE/2, BSIZE);   
  31.             while(buffer.hasRemaining()) {   
  32.                 modify(buffer);   
  33.             }   
  34.                
  35.             Thread.sleep(1000);// 此处要延迟,不然看不到效果   
  36.             mapBuffer.rewind();   
  37.             System.out.println(mapBuffer.limit());   
  38.             while(mapBuffer.hasRemaining()) {// 查看三个线程的修改效果   
  39.                 System.out.print((char)mapBuffer.get());   
  40.             }   
  41.                
  42.         } catch (FileNotFoundException e) {   
  43.             e.printStackTrace();   
  44.         } catch (IOException e) {   
  45.             e.printStackTrace();   
  46.         } catch (InterruptedException e) {   
  47.             e.printStackTrace();   
  48.         }   
  49.            
  50.     }   
  51.        
  52.     /*  
  53.      * capacity 为ByteBuffer的大小,在ByteBuffer创建时就被指定  
  54.      * position 为当前读/写操作数据的下标位置  
  55.      * limit 为ByteBuffer中有效数据的长度,在进行写操作时和capacity相等  
  56.      * mark 一个临时存放的位置下标。调用mark()会将mark设为当前的position的值,  
  57.      *      以后调用reset()会将position属性设置为mark的值。mark的值总是小于等于position的值,  
  58.      *      如果将position的值设的比mark小,当前的mark值会被抛弃掉。  
  59.      *   
  60.      * Buffer clear()  
  61.      *      把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用。  
  62.      * Buffer flip()  
  63.      *      把limit设为当前position,把position设为0,一般在从Buffer读出数据前调用。  
  64.      * Buffer rewind()  
  65.      *      把position设为0,limit不变,一般在把数据重写入Buffer前调用。  
  66.      */  
  67.     private static class LockAndModify extends Thread {   
  68.         private ByteBuffer buffer;   
  69.         private int start;   
  70.         private int end;   
  71.         public LockAndModify(ByteBuffer buffer, int start, int end) {   
  72.             buffer.limit(end);   
  73.             buffer.position(start);   
  74.             this.buffer = buffer.slice();// 创建新的缓冲区长度为end-start   
  75.             this.start = start;   
  76.             this.end = end;   
  77.             start();   
  78.         }   
  79.            
  80.         public void run() {   
  81.             try {   
  82.                 FileLock fl = fc.lock(start, end, false);// 锁住文件的一部分   
  83.                 while(buffer.position() < buffer.limit()) {   
  84.                     modify(buffer);   
  85.                 }   
  86.                    
  87.                 fl.release();// 释放锁   
  88.                    
  89.             } catch (IOException e) {   
  90.                 e.printStackTrace();   
  91.             }   
  92.         }   
  93.            
  94.     }   
  95.        
  96.     /**  
  97.      * 修改byteBuffer中的值  
  98.      * @param buffer  
  99.      */  
  100.     public static void modify(ByteBuffer buffer) {   
  101.         buffer.mark();// 记住此位置   
  102.         byte b = (byte)(buffer.get()+1);// 读取一个,下标移动到后一位置   
  103.         buffer.reset();// 将下标回到mark()位置   
  104.         buffer.put(b);// 改变此位置的值   
  105.     }   
  106. }  

相关内容