Vraag Evenement slechts één keer afgevuurd bij het bekijken van een map


Met behulp van de service java.nio bekijk ik een map en alle bijbehorende submappen:

Files.walkFileTree(projectPath, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
        watched.put(key, new WatchableDirectory(dir, projectPath));
        return FileVisitResult.CONTINUE;
    }
});

Dan wacht ik op gebeurtenissen:

executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                WatchKey key;
                while ((key = watcher.take()) != null) {
                    List<WatchEvent<?>> events = key.pollEvents();
                    WatchableDirectory watchableDirectory = watched.get(key);
                    for (WatchEvent<?> event : events) {
                         ....
                    }
             }
          ....
         }
    }

(watched is een Map dat bevat toewijzingen van een sleutel naar metadata over de map)

Alleen de eerste gebeurtenis voor een bepaalde map wordt echter geactiveerd. Telkens wanneer ik een ander bestand in een map verander, waar een bestand al is gewijzigd, gebeurt er niets (ik valideer dat door zowel een breekpunt te plaatsen als te verwachten dat de logica in de lus zal plaatsvinden).

Als ik echter een bestand in een andere map wijzig, dan werkt alles (nogmaals, alleen de eerste keer).

Geen uitzonderingen worden gegooid (er is een catch-clausule voor java.lang.Exception), en de lus loopt duidelijk nog steeds.

Ik dacht dat waarschijnlijk een keer geconsumeerd, de map kan worden uitgeschreven. Dus ik heb een regel toegevoegd om hem opnieuw te registreren nadat het bestand is afgehandeld. Geen effect.

Windows 7, Java 7.

Om het even welke ideeën waarom?


15
2017-11-24 20:25


oorsprong


antwoorden:


Vergeet niet te bellen

key.reset();

nadat je klaar bent met het gebruiken in je while lus.

De docs staat

Anders, als er hangende gebeurtenissen zijn voor het object dan dit horloge   sleutel wordt onmiddellijk opnieuw in de wachtrij geplaatst bij de bewakingsdienst. Als er geen zijn   In afwachting van gebeurtenissen wordt de wacht-toets in de parate toestand gebracht en zal deze worden   blijf in die staat totdat een gebeurtenis wordt gedetecteerd of de horloge-sleutel is   geannuleerd.

en

Kijktoetsen zijn veilig voor gebruik door meerdere gelijktijdige threads. Waar   er zijn verschillende threads die gesignaleerde sleutels van een horloge ophalen   service moet er dan op worden gelet dat de reset-methode is   alleen aangeroepen nadat de gebeurtenissen voor het object zijn verwerkt. Deze   zorgt ervoor dat één thread de gebeurtenissen voor een object op elk moment verwerkt   tijd.

Dus als u niet reset, is het alsof uw horloge is uitgeschakeld.

WatchKey#reset() retourneert een Booleaanse waarde voor als deze geldig is of niet. Behandel die zaak zoals uitgelegd in de zelfstudie.

Marko benadrukt:

Nadat de gebeurtenissen voor de sleutel zijn verwerkt, moet u de   toets terug naar de status Gereed door reset in te schakelen. Als deze methode terugkeert   false, de sleutel is niet langer geldig en de lus kan afsluiten. Deze stap is   erg belangrijk. Als u geen reset oproept, wordt deze sleutel niet ontvangen   verdere evenementen.


24
2017-11-24 20:39