WatchService:错过和未处理的事件

时间:2015-04-22 15:56:00

标签: java file events watchservice

我遇到了WatchService的问题。以下是我的代码片段:

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();

}

*首先,要知道watch()是在无限循环中调用的。

问题是,一次创建多个文件时,会丢失一些事件。例如,如果我将三个文件复制粘贴到“... / request”文件夹中,则只有一个文件被捕获,其他文件仍然没有发生,也没有触发OVERFLOW事件。在某些不同的计算机和操作系统中,它最多可以达到两个文件,但如果一个尝试3个或更多,则其余文件仍未触及。

我找到了一个解决方法,但我认为这不是最好的做法。这是流程:

该过程开始,然后在

停止
WatchKey watckKey = watcher.take();

如预期的那样(根据Processing events)。然后,我将3个文件放在“request”文件夹中,因此,处理将在

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

问题在这里。看起来这个线程如此快速地通过这条线,两个CREATED事件留在后面并且丢失,只有一个被占用。解决方法是在此正上方添加一条额外的行,如下所示:

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

这似乎是一个解决方案,至少对于三个和几个同步文件,但它根本不可扩展。 总而言之,我想知道是否有更好的解决方案来解决这个问题。仅供参考,我正在运行Win 7 64

提前多多感谢!

2 个答案:

答案 0 :(得分:2)

如果在无限循环内调用watch,那么你无限次创建监视服务因此失去事件的可能性,我建议做以下操作,调用你的方法watchservice一次:

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);
    });
}

答案 1 :(得分:1)

请确保重置您的watchKey。前面提到的一些答案没有,这也可以解释掉事件。我推荐Oracle官方文档中提供的示例:https://docs.oracle.com/javase/tutorial/essential/io/notification.html

请注意,即使正确使用文件服务,其可靠性也很大程度上取决于基础操作系统。通常,应将其视为不提供100%保证的尽力而为机制。