Java NiO – memory mapped file

I recently encountered this article, which provides a good introduction to memory mapping files and how it is shared between two processes The following is the code of the process of reading the file:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MemoryMapReader {

 /**
  * @param args
  * @throws IOException 
  * @throws FileNotFoundException 
  * @throws InterruptedException 
  */
 public static void main(String[] args) throws FileNotFoundException,IOException,InterruptedException {

  FileChannel fc = new RandomAccessFile(new File("c:/tmp/mapped.txt"),"rw").getChannel();

  long bufferSize=8*1000;
  MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY,bufferSize);
  long oldSize=fc.size();

  long currentPos = 0;
  long xx=currentPos;

  long startTime = System.currentTimeMillis();
  long lastValue=-1;
  for(;;)
  {

   while(mem.hasRemaining())
   {
    lastValue=mem.getLong();
    currentPos +=8;
   }
   if(currentPos < oldSize)
   {

    xx = xx + mem.position();
    mem = fc.map(FileChannel.MapMode.READ_ONLY,xx,bufferSize);
    continue;   
   }
   else
   {
     long end = System.currentTimeMillis();
     long tot = end-startTime;
     System.out.println(String.format("Last Value Read %s,Time(ms) %s ",lastValue,tot));
     System.out.println("Waiting for message");
     while(true)
     {
      long newSize=fc.size();
      if(newSize>oldSize)
      {
       oldSize = newSize;
       xx = xx + mem.position();
       mem = fc.map(FileChannel.MapMode.READ_ONLY,oldSize-xx);
       System.out.println("Got some data");
       break;
      }
     }   
   }

  }

 }

}

However, I raised some comments / questions about this approach:

If we only execute the reader on an empty file, it runs

long bufferSize=8*1000;
  MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY,bufferSize);
  long oldSize=fc.size();

This will allocate 8000 bytes and the file will now be expanded The returned buffer is limited to 8000 and the position is 0, so readers can continue to read empty data When this happens, the reader will stop because currentpos = = oldsize

It is said to be written now (the code is omitted because most of the content is simple and can be referenced from the website) – it uses the same buffer size, so it will first write 8000 bytes, and then allocate another 8000 to expand the file Now, if we assume that this process pauses, and then we go back to the reader, the reader will see the new size of the file and allocate the rest (from position 8000 to 1600) and start reading again, reading another garbage

I'm a little confused about whether I have the reason to synchronize these two operations As far as I know, any call to map may extend the file. In fact, it is an empty buffer (filled with zeros) or the writer may have just extended the file but haven't written anything yet

Solution

There are several ways

>Give authors exclusive access to areas that have not yet been written Release the lock after writing everything This is compatible with every other application running on the system, but it requires the reader to be smart enough to retry a failed read unless you use it in conjunction with one of the other methods > use another communication channel, such as a pipe or socket or the metadata channel of a file, to let the author tell the reader about the completed write. > Write a special tag (as part of the protocol) at a location in the file to tell the written data, such as

MappedByteBuffer bb;
…
// write your data

bb.force();// ensure completion of all writes
bb.put(specialPosition,specialMarkerValue);
bb.force();// ensure visibility of the marker
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>