2012-03-28 4 views
2

ich versuche, eine Datei zu sperren und unten, um es mit dem Code schreiben:Warum passiert beim Sperren einer Datei eine OverlappingFileLockException?

public class TrainSetBuildTask implements Runnable { 
    private String pathname; 
    public TrainSetBuildTask(String pathname){ 
     this.pathname = pathname; 
    } 

    @Override 
    public void run() { 
      try { 
       String content = "content\n"; 
      //write to a file 
      FileOutputStream os = new FileOutputStream(new File(pathname), true); 
      FileChannel channel = os.getChannel(); 
      FileLock lock = channel.tryLock(); 
      if (lock != null) { 
       ByteBuffer bytes = ByteBuffer.wrap(content.getBytes()); 
       channel.write(bytes); 
       lock.release(); 
      } 
      channel.close(); 
      os.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 
} 

Und neue zwei Gewinde mit Instanzen der Klasse:

String pathname = "/home/sjtu123/test.arff"; 
    TrainSetBuildTask task1 = new TrainSetBuildTask(pathname); 
    Thread t1 = new Thread(task1); 
    TrainSetBuildTask task2 = new TrainSetBuildTask(pathname); 
    Thread t2 = new Thread(task2); 
    t1.start(); 
    t2.start(); 

Dann erhalte ich die Fehler OverlappingFileLockException. Ich frage mich, warum das passiert, da ich die Datei nur einmal in jedem Thread sperre? Wie kann ich meinen Code reparieren?

Antwort

2

Sie können nicht die gleiche Datei mehr sperren als einmal gleichzeitig. Entweder müssen Sie Java Lock-Objekte verwenden, um sicherzustellen, dass nur ein Thread versucht, die Datei zu einem Zeitpunkt zu sperren, oder die Threads auf andere Weise koordinieren, um zu warten, bis kein anderer Thread mehr blockiert.

Vom manual:

Dateisperren werden im Namen der gesamten virtuellen Java-Maschine gehalten. Sie sind nicht geeignet, um den Zugriff auf eine Datei durch mehrere Threads innerhalb derselben virtuellen Maschine zu steuern.

+0

Dann was ist die Verwendung von 'FileLock', da es nicht verwendet werden kann, um die Threads zu koordinieren, die Datei schreiben will? @Attila –

+0

Es soll verhindern, dass andere (z. B. andere Programme) gleichzeitig mit der Datei, die die Sperre enthält, auf die Datei zugreifen. Die Ausnahme gibt an, dass eine andere Person (in diesem Fall einer Ihrer eigenen Threads) die Datei bereits gesperrt hat. Wenn Sie (aus der Perspektive Ihres Programms) nicht aufgeben wollen, können Sie es später versuchen, zum Beispiel in der Hoffnung, dass zu diesem Zeitpunkt die Sperre aufgehoben wird. – Attila

+0

Ich habe das Handbuch gelesen, bevor ich diesen Code oben schreibe und verstehe nicht die Bedeutung von ihnen. Jetzt verstehe ich es, danke. @Attila –

2

Dateien werden global gesperrt, nicht nur pro Thread oder pro Prozess.

Sie benötigen zwei Faden nacheinander wie folgt auszuführen:

String pathname = "/home/sjtu123/test.arff"; 
TrainSetBuildTask task1 = new TrainSetBuildTask(pathname); 
Thread t1 = new Thread(task1); 
TrainSetBuildTask task2 = new TrainSetBuildTask(pathname); 
Thread t2 = new Thread(task2); 
t1.start(); 
t1.join(); // Wait for t1 to die. 
t2.start(); 

Neue Version nach Kommentare:

FileWriter pathname = new FileWriter("/home/sjtu123/test.arff"); 
TrainSetBuildTask task1 = new TrainSetBuildTask(pathname); 
Thread t1 = new Thread(task1); 
TrainSetBuildTask task2 = new TrainSetBuildTask(pathname); 
Thread t2 = new Thread(task2); 
t1.start(); 
t2.start(); 
t1.join(); 
j2.join(); 
synchronized (pathname){ 
    pathname.close(); 
} 

und

public class TrainSetBuildTask implements Runnable { 
    private FileWriter pathname; 
    public TrainSetBuildTask(FileWriter pathname){ 
     this.pathname = pathname; 
    } 

    @Override 
    public void run() { 
      try { 
      // Do work 
      synchronized (pathname){ 
      // Write to file 
      } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 
} 
+0

Ich hoffe, dass t2 einige Jobs außer dem Schreiben in die Datei tun kann. Aber Ihr Code bedeutet, dass Thread t2 erst dann zu arbeiten beginnt, wenn der Thread t1 seine Arbeit beendet hat, egal, ob t2 die von t1 gesperrte Datei schreiben möchte. @Johannes –

+0

Das war bei der Frage nicht ganz offensichtlich, aber schau dir stattdessen die neue Version an. Es ist vielleicht nicht 100% richtig, aber Sie sollten die allgemeine Idee bekommen. – Johannes

Verwandte Themen