2013-04-25 65 views
2

我有一個監視服務,監視ENTRY_DELETEENTRY_CREATEENTRY_MODIFY事件的目錄,並根據事件執行邏輯。如何將WatchService轉換爲Runnable?

我需要服務來觀察所有更改的目錄,而不是退出循環。但我也需要啓發我的另一個邏輯。

如何將這些方法重構爲Runnable來完成此操作?

下面是代碼。

public static void main(String[] args) {   
    System.out.println("Started watching"); 
    FileServices fileServices = new FileServicesImpl(); 

    fileServices.setSrcDir(fileServices.getValue("srcdir","properties/abc.properties")); 
    fileServices.setDestDir(fileServices.getValue("destdir","properties/abc.properties")); 

    System.out.println(fileServices.getSrcDir()); 
    System.out.println(fileServices.getDestDir()); 

    Map<String,WatchEvent> files = new HashMap<>(); 
    MappingConsole mappingConsole = new MappingConsole(); 

    for(;;){ 
     files = fileServices.getEventMap(); 
     for(String f : files.keySet()){ 
      System.out.println("Size of files: "+files.size()); 
      if (files.get(f).kind() == ENTRY_CREATE || files.get(f).kind() == ENTRY_MODIFY) { 
       System.out.println("Processing: " +f); 
       mappingConsole.map940(fileServices.getSrcDir(),f,fileServices.getDestDir()); 
       System.out.println("Processed: " +f); 
      } 
     } 
    } 

} 

從FileServicesImpl:

@Override 
public void monitorSrcDir(String srcDir){ 
    for(;;){ 
     try { 
      WatchService watchService = FileSystems.getDefault().newWatchService(); 
      Path myDir = Paths.get(srcDir); 
      WatchService watcher = myDir.getFileSystem().newWatchService(); 
      myDir.register(watcher, ENTRY_CREATE,ENTRY_DELETE, ENTRY_MODIFY); 
      WatchKey watchKey = watcher.take(); 
      List<WatchEvent<?>> events = watchKey.pollEvents(); 
      for (WatchEvent event : events) { 
       if (event.kind() == ENTRY_CREATE) { 
        System.out.println("Create: " + event.context().toString()); 
        getEventMap().put(event.context().toString(), event); 
       } 
       if (event.kind() == ENTRY_DELETE) { 
        System.out.println("Delete: " + event.context().toString()); 
        getEventMap().put(event.context().toString(), event); 
       } 
       if (event.kind() == ENTRY_MODIFY) { 
        System.out.println("Modify: " + event.context().toString()); 
        getEventMap().put(event.context().toString(), event); 
       } 
      } 
      watchKey.reset(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

回答

1

我這樣做:

public class WatchServiceMonitor implements Monitor, Runnable, Closeable { 
    private static Logger log = LoggerFactory.getLogger(WatchServiceMonitor.class.getName()); 
    private Destination destination; 
    private Path hotFolder; 
    private Thread thread; 

    public WatchServiceMonitor(Path hotFolder, Destination destination) { 
     this.hotFolder = hotFolder; 
     this.destination = destination; 

    } 

    @Override 
    public void close() throws IOException { 
     try { 
      stop(); 
     } 
     catch (InterruptedException e) { 
      log.warn("request to stop failed, guess its time to stop being polite!"); 
     } 
    } 

    @Override 
    public void join() throws InterruptedException { 
     thread.join(); 
    } 

    @Override 
    public void run() { 
     try (WatchService watcher = FileSystems.getDefault().newWatchService()) { 
      if (log.isTraceEnabled()) log.trace("registering create watcher on " + hotFolder.toAbsolutePath().toString()); 
      hotFolder.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); 
      if (log.isDebugEnabled()) log.debug("watcher registration complete for " + hotFolder.toAbsolutePath().toString()); 
      synchronized (this) { 
       this.notifyAll(); 
      } 
      for (;;) { 
       if (thread.isInterrupted()) break; 

       WatchKey key = null; 
       try { 
        log.trace("waiting for create event"); 
        key = watcher.take(); 
        log.trace("got an event, process it"); 
       } 
       catch (InterruptedException ie) { 
        log.trace("interruped, must be time to shut down..."); 
        break; 
       } 

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

        if (kind == StandardWatchEventKinds.OVERFLOW) return; 

        @SuppressWarnings("unchecked") 
        WatchEvent<Path> eventPath = (WatchEvent<Path>) eventUnknown; 
        Path path = hotFolder.resolve(eventPath.context()); 
        log.trace("calling destination.transfer({})", path); 
        destination.transfer(path); 
        log.info("transferred {} to destination"); 

        if (! key.reset()) { 
         break; 
        } 
       } 
      } 
     } 
     catch (IOException ioe) { 
      log.error(ioe.getMessage(), ioe); 
     } 
     log.debug("existing run loop"); 
    } 

    @Override 
    public void start() throws InterruptedException { 
     log.trace("starting monitor"); 
     thread = new Thread(this); 
     thread.start(); 
     synchronized (this) { 
      this.wait(); 
     } 
     log.trace("monitor started"); 
    } 

    @Override 
    public void stop() throws InterruptedException { 
     log.trace("stopping monitor"); 
     thread.interrupt(); 
     thread.join(); 
     thread = null; 
     log.trace("monitor stopped"); 
    } 
} 

Destination類是我自己的一個知道如何從由WatchService事件指示的路徑轉移。

所以,實質上我只是將整個WatchService循環包裝在Runnable實例的run方法中。

+0

謝謝,給了我一大堆工作 – 2013-04-25 15:10:35

+0

從你的代碼的外觀來看,你正在做的和我正在做的事很相似。希望這可以幫助。 – Lucas 2013-04-25 15:12:24