我有一个目录监视器的工作实现,它递归地注册自己和给定路径的子目录。
我遇到的问题是我有特定的行为同步行为以在不同的目录上执行并防止它变得非常混乱我想实例化我的DirectoryWatcher
的实例并将其传递给我{{1}的实例1}}类将能够推断出正确的行为。
我遇到的问题是我无法创建目录监视类的两个实例,因为只有实例化的第一个实例才会实际监视目录。
代码段:
Syncer
创建单个实例(有效):
private final WatchService watcher;
private final Map<WatchKey, Path> keys;
private final boolean recursive;
private boolean trace = false;
private final Syncer syncer;
public DirectoryWatcher(Path dir, boolean recursive, Syncer syncer) throws IOException {
this.syncer = syncer;
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey, Path>();
this.recursive = recursive;
if (recursive) {
logger.info("Watching Directory {} ...", dir);
registerAll(dir);
logger.info("Registered Directory {} ...", dir);
} else {
register(dir);
}
// enable trace after initial registration
this.trace = true;
}
输出:
new DirectoryWatcher(path, true, new Syncer(path, path2, "some extra key")).processEvents();
尝试拥有多个实例:
[main] INFO Controller.directory.DirectoryWatcher - Watching Directory /some/path ...
[main] INFO Controller.directory.DirectoryWatcher - Registered Directory /some/path ...
输出:
new DirectoryWatcher(path, true, new Syncer(path, path2, "some extra key")).processEvents();
new DirectoryWatcher(path2, true, new Syncer(path2, path, "some extra key part 2")).processEvents();
似乎永远不会看第二个目录([main] INFO Controller.directory.DirectoryWatcher - Watching Directory /some/path ...
[main] INFO Controller.directory.DirectoryWatcher - Registered Directory /some/path ...
)。
我可以在同一个实例上注册多个路径,但这不是我追求的功能。
我也尝试将观察者放在path2
内,但同样的问题仍然存在。
编辑:
添加runnable.run()
和register
方法:
registerAll
编辑2:添加了private void registerAll(final Path start) throws IOException {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
register(dir);
return FileVisitResult.CONTINUE;
}
});
}
private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
if (trace) {
Path prev = keys.get(key);
if (prev == null) {
logger.info("Register: {}", dir);
} else {
if (!dir.equals(prev)) {
// System.out.format("update: %s -> %s\n", prev, dir);
logger.info("Update: {} -> {}", prev, dir);
}
}
}
keys.put(key, dir);
}
processEvents()
答案 0 :(得分:0)
如果我得到了正确的答案,你在同一个帖子中实例化DirectoryWatchers
?
如果这是真的,那么第二个实例永远不会启动,因为线程仍在执行第一个观察者的无限processEvents
循环。您必须在不同的线程中启动两个观察者才能并行执行。例如,您可以实例化ExecutorService
并将您的runnables提交给此服务:
final DirectoryWatcher watcher1 = new DirectoryWatcher(path, true,
new Syncer(path, path2, "some extra key"));
final DirectoryWatcher watcher2 = new DirectoryWatcher(path2, true,
new Syncer(path2, path, "some extra key part 2"));
final ExecutorService tExecutorService = Executors
.newCachedThreadPool();
tExecutorService.submit(watcher1::processEvents);
tExecutorService.submit(watcher2::processEvents);
只需将代码置于Runnable
内即可并行执行Runnables
...