您对事件的循环是有缺陷的,因为它会跳过事件,因为您有两次调用watchService.take()
。第二个调用可能会阻塞,如果它有效,事件将被跳过,因此内部循环可能永远不会正确匹配删除或退出。删除第二个take()
:
while ((key = watchService.take()) != null) {
...
while ((key = watchService.take()) != null) {
...
这是设置 WatchService 的逻辑示例,您应该尝试使用System.out.println()
了解它是如何工作的:
Path watchDir = Path.of("whatever");
try (WatchService service = watchDir.getFileSystem().newWatchService()) {
// Add whatever StandardWatchEventKinds events you need
WatchKey wk = watchDir.register(service, StandardWatchEventKinds.ENTRY_DELETE /*, ENTRY_CREATE ENTRY_DELETE ... ETC */);
// Insert your own loop termination condition here:
while (running) {
WatchKey key = service.poll(1, TimeUnit.SECONDS);
if (key == null) {
continue;
}
for (var event : key.pollEvents()) {
Path evPath = (Path) event.context();
Path absPath = ((Path) key.watchable()).resolve(evPath);
Kind<?> kind = event.kind();
System.out.println("Kind=" + kind + " Path=" + evPath+" AbsPath=" + absPath);
// Check each event to see if your termination condition is met
}
key.reset();
}
}
运行上面的命令应该会让您了解什么WatchService
提供,您可以将自己的逻辑填写到pollEvents()
循环处理每个删除通知:
// Check each event to see if your termination condition is met
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
if (absPath is one of the files you want) {
Mark as received + print timings
running = (number of remaining files you want > 0);
}
}
您可能会发现将监视服务部分重构为单独的组件更容易,以便它整理事件并将一组更改传递给侦听器 - 请参阅例子在这里 https://stackoverflow.com/questions/65223686/java-watchservice-perform-action-on-event-using-threads/65251819#65251819.
如果循环内的侦听器/处理程序可能需要一些时间,请在单独的线程中运行监视服务和处理程序,以便事件循环跟上监视事件发布,并且不要使用sleep
因为这可能会导致溢出事件,因为您的侦听器/处理程序太慢。