Java-NIO - Memory-mapped-Dateien

Ich kam vor kurzem in diesem Artikel, die eine nette Einführung in die memory-mapped-Dateien und wie kann Sie geteilt werden zwischen zwei Prozessen. Hier ist der code für einen Prozess, der liest in der Datei:

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, 0, 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,xx , oldSize-xx);
       System.out.println("Got some data");
       break;
      }
     }   
   }

  }

 }

}

Habe ich allerdings ein paar Kommentare/Fragen zu diesem Ansatz:

Wenn wir führen den Leser nur eine leere Datei, ich.e führen Sie

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

Diese Zuordnung 8000 bytes, die jetzt erweitern Sie die Datei. Der Puffer, das gibt ein limit von 8000 und eine position von 0, daher kann der Leser gehen Sie und Lesen Sie leere Daten. Nachdem dies passiert ist, den Leser zu stoppen, als currentPos == oldSize.

Angeblich jetzt der Schriftsteller kommt in (code weggelassen, da die meisten es unkompliziert ist und auf die verwiesen werden kann, die von der website) - es verwendet die selbe Puffer-Größe, so schreibt er ersten 8000 Byte, dann reservieren Sie einen anderen 8000, die Erweiterung der Datei. Nun, wenn wir annehmen, dieser Prozess hält an diesem Punkt, und wir gehen zurück an das Lesegerät, dann wird der Leser sieht die neue Größe der Datei und ordnet den Rest (also von 8000 bis 1600) und fängt an zu Lesen auch das Lesen in einem anderen Müll.

Ich bin ein bisschen verwirrt, ob es ein warum zu synchronisieren diese beiden Operationen. Soweit ich es sehe, ist jeder Aufruf zur map verlängern könnte die Datei mit einer leeren Puffer (mit Nullen gefüllt) oder der Schriftsteller könnte nur die Datei erweitert, hat aber nichts mehr geschrieben, in der es noch nicht...

Immer wenn ich unter "schreiben" und "gemeinsam genutzte Daten", ich denke die Synchronisation benötigt werden.
Ich weiß nicht, was du damit meinst, ob es ein warum zu synchronisieren', aber die Eröffnung viele memory-mapped-Dateien, oder das gleiche mehrmals, ist eine sehr schlechte Idee, jedenfalls für die garbage-collection Gründen, da es keine genau definierte Zeit, die das Gedächtnis betreffenden freigegeben werden können. Und es gibt keinen besonderen Vorteil für die Kartierung in kleinen Mengen wie 8k: Sie kann genauso gut mit buffered streams, die so viel Pufferung von Standard -, und keine dieser malarkey, was zu tun ist, wenn die Datei erweitert. Die zugeordneten Dateien sind am besten, wenn verwendet auf eine sehr kleine Zahl, wie etwa eins, von sehr großen Dateien.
OK, habe es - öffnen einer großen Datei. Noch, dies ist der Mittelwert für IPC, so möchte ich wissen, wie das erreicht werden kann, i..e ein Prozeß schreibt, der andere liest, aber in einer Weise, dass wir wissen, dass der andere Prozess tatsächlich schrieb sth, bevor wir Lesen können. Dies ist die Synchronisierung von ich spreche
Es ist eine Datei, nicht ein Rohr. Mithilfe von mmap() allein wird nicht zulassen, Sie zu synchronisieren. Der Beispielcode stellt (hässlich) busy-polling.

InformationsquelleAutor Bober02 | 2014-03-03

Schreibe einen Kommentar