我想问你一个有关 WatchService
的问题。因此,我有代码在目录中出现时正在重命名特定文件。但是我想设置WatchService
的超时运行时间,如果目录内什么都没发生。
,但是我从我阅读的内容中。有超时,但仅在开始监视目录之前睡觉。
因此,代码看起来像:
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-with-Resources完成后,此代码也关闭WatchService
。它还返回Optional
而不是使用Consumer
。Predicate
将与isPdfFile(...)
做同样的事情。我这样做是因为它使该方法独立(这对一个示例来说是有益的),但是如果需要,您可以继续使用isPdfFile
和Consumer
。使用该方法可能看起来像:
Path dir = ...;
watch(dir, file -> isPdfFile(file)).ifPresent(/* do something */);
顺便说一句,您的代码使用take()
并检查它是否返回null
。该方法切勿返回null
,因为它需要等到事件可用。换句话说,它返回WatchKey
或投掷。