我想问你一个关于WatchService的问题.因此,当目录中出现我要重命名特定文件的代码.但是我想将WatchService的超时设置为2分钟(如果目录内没有任何反应).
但是从我的读物来看.有超时,但仅在启动监视目录之前处于睡眠状态.
因此,代码如下所示:
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Paths.get(dirPath).register(watchService,StandardWatchEventKinds.ENTRY_CREATE);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
String fileName = event.context().toString();
if (isPdfFile(fileName)) {
consumer.accept(dirPath + fileName);
return;
}
}
key.reset();
}
}
catch (IOException | InterruptedException e) {}
还是有其他解决方法?
最佳答案
如果要在等待事件时超时,则需要使用
WatchService.poll(long,TimeUnit)
.如果我正确地理解了您的问题,则需要等待两分钟,在第一个匹配事件上发生短路.在这种情况下,您需要跟踪到目前为止实际等待了多长时间,以及剩余时间的超时情况.否则,您将在每个循环中等待两分钟,或者更糟糕的是,在第一个不匹配事件上退出该方法.我相信以下(未经测试)的代码应类似于您想要的代码:
public static Optional<Path> watch(Path directory,Predicate<? super Path> filter)
throws IOException {
try (WatchService service = directory.getFileSystem().newWatchService()) {
directory.register(service,StandardWatchEventKinds.ENTRY_CREATE);
long timeout = TimeUnit.NANOSECONDS.convert(2L,TimeUnit.MINUTES);
while (timeout > 0L) {
final long start = System.nanoTime();
WatchKey key = service.poll(timeout,TimeUnit.NANOSECONDS);
if (key != null) {
for (WatchEvent<?> event : key.pollEvents()) {
Path context = (Path) event.context();
if (filter.test(context)) {
return Optional.of(directory.resolve(context));
}
}
key.reset();
// Accounts for the above execution time. If you don't want that you
// can move this to before the "for" loop.
timeout -= System.nanoTime() - start;
} else {
break;
}
}
} catch (InterruptedException ignore) {}
return Optional.empty();
}
使用try-with-resources完成后,此代码还将关闭WatchService.它还会返回Optional
,而不是使用Consumer.谓词将与isPdfFile(…)做相同的事情.我这样做是因为它使方法独立(这对示例很有用),但是如果需要,您可以继续使用isPdfFile和Consumer.使用该方法可能类似于:
Path dir = ...;
watch(dir,file -> isPdfFile(file)).ifPresent(/* do something */);
顺便说一句,您的代码使用take()
并检查它是否返回null.该方法永远不要返回null,因为它会等待事件可用.换句话说,它返回一个WatchKey或throw.