我有点惊讶Watch Service应该作为带有轮询循环的进程/线程来实现。我不记得Java中应该做的任何其他API。
将它实现为一组回调(侦听器,观察者等等)会不会更好?
BTW - 是否有任何第三方库几乎完全相同,但使用回调模型?答案 0 :(得分:4)
Apache Commons有一些文件监视服务,我认为它比Java 7好得多。我不确定它们是否使用回调,但在我看来它们更直观。
是的,我认为观察者模型会好得多。我在某处读到,使用Java做这件事有点困难,因为它通过虚拟机运行,并且需要直接与操作系统对话的文件的监听器。我不确定这个的细节或有效性。
答案 1 :(得分:4)
我建立在Alexeis的答案上,但我认为他不够清楚......看看这个示例代码:
WatchService service = dir.getFileSystem().newWatchService();
WatchKey key = dir.register(service, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
System.out.println(key);
for(;;) {
WatchKey k = service.take();
System.out.println(k);
for(WatchEvent<?> ev:k.pollEvents()) {
System.out.println(ev.kind());
if(ev.kind() == OVERFLOW) continue;
//TODO
System.out.println(ev.context());
}
if(!k.reset()) break;
}
key.cancel();
如果您检查println(key)
/ println(k)
输出,您会看到一遍又一遍地返回相同的对象;每次发出密钥时都会返回take()
,因此要使用具有相同WatchService
的多个密钥,只需检查每次返回的密钥。这也意味着只要密钥没有发出信号,你的循环就会阻塞 - 正是你想要的。
if(!k.reset()) break;
也至关重要;这是我在写Alexais回答的评论时忘了的。我的假设是take()
由register()
调用,因此我的用户代码中不应返回任何密钥,因为register()已经使用了它。由于这种错误的假设,我不知道实际发生了什么。
答案 2 :(得分:3)
您不必使用轮询,您可以使用WatchService.take(),它会在发生更改时立即返回。是的,它需要一个线程,但是单个线程可以用于被监视的多个对象。所以很容易实现拥有一个监视线程并允许为每个对象注册回调的单例。
至于第三方图书馆,请查看Guava EventBus。我没有尝试过,也不确定它是否符合您的需求。