我创建了一个小型Java应用程序,用于监视文件夹。它使用observer模式来通知不同的fileHandler。文件处理程序操作可能需要几秒钟的时间来处理文件。如果它一次只处理一个项目,那么一切都会很好。如果一个新文件在前一个文件完成之前到达,它将错过该事件,并且不会检测到新文件。解决这个问题的最佳模式是什么?我代码的某些部分。。。
WatchService watcher = FileSystems.getDefault().newWatchService();
List<Path> allPaths = new ArrayList<Path>();
Path path = Paths.get("c:InPutFolder");
allPaths.add(path);
// Register all paths in the WatchService
Map<WatchKey, Path> allKeys = new HashMap<>();
for (Path path : allPaths) {
WatchKey key = path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
allKeys.put(key, path);
}
// Monitor the folders and listen for change notification.
while (true) {
WatchKey key = watcher.take();
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (ENTRY_CREATE.equals(kind)) {
Path path = allKeys.get(key);
// Store item in arrayList of objects
Item item = new Item(path.toString(), event.context().toString());
ic.addItem(item);
notifyObservers(); // NOTIFY OBSERVERS & EXECUTE LONG PROCESS
}
}
key.reset();
}
我有一个类似的实现,它有一个等待文件的服务。来自本文
当轮询或获取API返回WatchKey实例时,如果重置API而不调用,它将不会捕获更多事件
因此,在take
和reset
调用之间,您不会接收到事件。解决方案是获取事件(或事件中的数据(并尽快调用reset。我使用线程池,并在Runnable
实例中处理每个事件。如果您想走线程化的道路,请查看java的ExecutorService
。但是,您需要确保无论您的长时间运行的进程调用什么都是线程安全的。
没有理由不能获取所有事件信息,然后调用reset并在reset调用后同步处理事件。如果你这样做了,你可能应该捕捉OVERFLOW
事件,这样你就知道什么时候错过了事件。