2015-04-22 17 views
5

Ho riscontrato un problema con WatchService. Ecco un frammento del mio codice:WatchService: eventi mancati e non gestiti

public void watch(){ 
    //define a folder root 
    Path myDir = Paths.get(rootDir+"InputFiles/"+dirName+"/request");  

    try { 
    WatchService watcher = myDir.getFileSystem().newWatchService(); 
    myDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); 

    WatchKey watckKey = watcher.take(); 

    List<WatchEvent<?>> events = watckKey.pollEvents(); 
    for (WatchEvent event : events) { 
     //stuff 
    } 
    }catch(Exception e){} 

    watckKey.reset(); 

} 

* Prima di tutto, sanno che orologio() viene chiamato all'interno di un ciclo infinito.

Il problema è che quando si creano più file alla volta, mancano alcuni eventi. Ad esempio, se copio tre file nella cartella ".../request", ne viene catturato solo uno, gli altri rimangono come se nulla fosse accaduto, né viene attivato un evento OVERFLOW. In alcuni computer e sistemi operativi diversi, raggiunge fino a due file, ma se si tenta di eseguire 3 o più, il resto rimane intatto.

Ho trovato una soluzione, ma non penso che sia la migliore pratica. Questo è il flusso:

Le avviato il processo e quindi si arresta

WatchKey watckKey = watcher.take(); 

come previsto, (come da Processing events). Quindi, faccio cadere 3 file insieme nella cartella "richiesta", quindi, riprende il processo al

List<WatchEvent<?>> events = watckKey.pollEvents(); 

Il problema è qui. Sembra che il filo passi così velocemente attraverso questa linea che due eventi CREATI rimangono indietro e sono persi, ne viene preso solo uno. La soluzione era quella di aggiungere una riga aggiuntiva proprio sopra questo, come questo:

Thread.sleep(1000); 
List<WatchEvent<?>> events = watckKey.pollEvents(); 

questa sembra essere una soluzione, almeno per tre e diversi file più contemporaneamente, ma non è scalabile a tutti. Quindi, in conclusione, vorrei sapere se esiste una soluzione migliore per questo problema. A proposito, sto gestendo una Win 7 64

Grazie mille in anticipo!

risposta

1

Se orologio viene chiamato all'interno di un ciclo infinito, allora si sta creando un servizio orologio infinita senza di volte da qui la possibilità di perdere eventi, vorrei suggerire fare quanto segue, Chiamate il vostro metodo di watchservice una volta:

public void watchservice() 
{ 
    Thread fileWatcher = new Thread(() -> 
    { 
     Path path = Paths.get(rootDir+"InputFiles/"+dirName+"/request"); 
     Path dataDir = Paths.get(path);  

     try 
     { 
      WatchService watcher = dataDir.getFileSystem().newWatchService(); 
      dataDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); 

      while (true) 
      { 
       WatchKey watckKey; 
       try 
       { 
        watckKey = watcher.take(); 
       } 
       catch (Exception e) 
       { 
        logger.error("watchService interupted:", e); 
        return; 
       } 
       List<WatchEvent<?>> events = watckKey.pollEvents(); 
       for (WatchEvent<?> event : events) 
       { 
        logger.debug("Event Type : "+ event.kind() +" , File name found :" + event.context()); 
        if (event.kind() != StandardWatchEventKinds.OVERFLOW) 
        { 
         // do your stuff 
        } 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      logger.error("Error: " , e); 
     } 
    }); 
    fileWatcher.setName("File-Watcher"); 
    fileWatcher.start(); 

    fileWatcher.setUncaughtExceptionHandler((Thread t, Throwable throwable) -> 
    { 
     logger.error("Error ocurred in Thread " + t, throwable); 
    }); 
} 
+0

Ad un certo punto nel mio codice ho fatto questo, ho preso la creazione del servizio orologio fuori dal ciclo infinito. Non ricordo esattamente perché, e non ho provato di nuovo questa situazione. La soluzione alternativa è ancora lì comunque – McCoy