2017-05-21 6 views
0

Ich habe einen Watcher, der meine Datenstrukturen aktualisiert, wenn eine Änderung gehört wird. Wenn die Änderung jedoch nicht sofort erfolgt (d. H. Wenn eine große Datei von einem anderen Dateisystem kopiert wird oder ein großer Teil der Datei geändert wird), versucht die Datenstruktur zu früh zu aktualisieren und gibt einen Fehler aus.Java Watch Service - Warte, bis die Änderungen abgeschlossen sind

Wie kann ich meinen Code ändern, so dass updateData() nach nur die letzten genannt wird ENTRY_MODIFY genannt wird, statt nach jedem einzelnen ENTRY_MODIFY.

private static boolean processWatcherEvents() { 
    WatchKey key; 
    try { 
     key = watcher.poll(10, TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     return false; 
    } 

    Path directory = keys.get(key); 
    if (directory == null) { 
     return false; 
    } 

    for (WatchEvent <?> event : key.pollEvents()) { 
     WatchEvent.Kind eventKind = event.kind(); 

     WatchEvent <Path> watchEvent = (WatchEvent<Path>)event; 
     Path child = directory.resolve(watchEvent.context()); 

     if (eventKind == StandardWatchEventKinds.ENTRY_MODIFY) { 
      //TODO: Wait until modifications are "finished" before taking these actions. 
      if (Files.isDirectory(child)) { 
       updateData(child); 
      } 
     } 

     boolean valid = key.reset(); 
     if (!valid) { 
      keys.remove(key); 
     } 
    } 

    return true; 
} 
+0

Haben Sie assign Kind zu einem varialbe, und nach der Schleife beenden, führen updateDate versucht? Oder ich vermisse die Idee hier? – Beri

+0

Ich denke, die Antwort, die ich [hier] (http://stackoverflow.com/a/34718685/243373) gab, könnte das sein, was du brauchst, zumindest die Umrisse. –

+0

War die Antwort in dem Link, den ich von irgendeinem Gebrauch gab? –

Antwort

0

Ihr Problem kann mit Zeitstempel gelöst werden. Erstellen Sie eine Karte zum Speichern des Zeitstempels in der Karte.

Map<Path, Long> fileTimeStamps; 

Für Prozessereignis den letzten modifizierten Zeitstempel überprüfen.

0

Ich schrieb einen Thread, der eine Liste von Dingen hält, die ich aktualisieren möchte, und Verzögerungen, die tatsächlich aktualisiert werden, bis 80 Millisekunden vergangen sind. Immer wenn ein ENTRY_MODIFY Ereignis auftritt, setzt es den Zähler zurück. Ich denke, das ist eine gute Lösung, aber es könnte besser sein?

@SuppressWarnings({ "rawtypes", "unchecked" }) 
private static boolean processWatcherEvents() { 
    WatchKey key; 
    try { 
     key = watcher.poll(10, TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     return false; 
    } 

    Path directory = keys.get(key); 
    if (directory == null) { 
     return false; 
    } 

    for (WatchEvent <?> event : key.pollEvents()) { 
     WatchEvent.Kind eventKind = event.kind(); 

     WatchEvent <Path> watchEvent = (WatchEvent<Path>)event; 
     Path child = directory.resolve(watchEvent.context()); 

     if (eventKind == StandardWatchEventKinds.ENTRY_CREATE) { 
      if (Files.isDirectory(child)) { 
       loadMe.add(child); 
      } else { 
       loadMe.add(child.getParent()); 
      } 

     } else if (eventKind == StandardWatchEventKinds.ENTRY_DELETE) { 
      //Handled by removeMissingFiles(), can ignore. 

     } else if (eventKind == StandardWatchEventKinds.ENTRY_MODIFY) { 
      System.out.println("Modified: " + child.toString()); //TODO: DD 
      if (Files.isDirectory(child)) { 
       modifiedFileDelayedUpdater.addUpdateItem(child); 
      } else { 
       modifiedFileDelayedUpdater.addUpdateItem(child); 
      } 

     } else if (eventKind == StandardWatchEventKinds.OVERFLOW) { 
      for (Path path : musicSourcePaths) { 
       updateMe.add(path); 
      } 
     } 

     boolean valid = key.reset(); 
     if (!valid) { 
      keys.remove(key); 
     } 
    } 

    return true; 
} 

...

class UpdaterThread extends Thread { 
    public static final int DELAY_LENGTH_MS = 80; 
    public int counter = DELAY_LENGTH_MS; 

    Vector <Path> updateItems = new Vector <Path>(); 

    public void run() { 
     while (true) { 
      long sleepTime = 0; 
      try { 
       long startSleepTime = System.currentTimeMillis(); 
       Thread.sleep (20); 
       sleepTime = System.currentTimeMillis() - startSleepTime; 
      } catch (InterruptedException e) {} //TODO: Is this OK to do? Feels like a bad idea. 

      if (counter > 0) { 
       counter -= sleepTime; 

      } else if (updateItems.size() > 0) { 
       Vector <Path> copyUpdateItems = new Vector<Path> (updateItems); 
       for (Path path : copyUpdateItems) { 
        Library.requestUpdate (path); 
        updateItems.remove(path); 

       } 
      } 
     } 
    } 

    public void addUpdateItem (Path path) { 
     counter = DELAY_LENGTH_MS; 
     if (!updateItems.contains(path)) { 
      updateItems.add (path); 
     } 
    } 
}; 
Verwandte Themen