监视服务Java7轮询循环

58wvjzkj  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(222)

我有点惊讶,watch服务应该被实现为一个带有轮询循环的进程/线程。我不记得java中还有其他api应该这么做。
将它实现为一组回调(侦听器、观察者等)不是更好吗?
顺便说一句,有没有第三方库可以做到几乎相同,但使用回调模型?

3pmvbmvn

3pmvbmvn1#

apachecommons有一些文件监视服务,我认为这些服务比java7中的要好得多。我不确定他们是否使用回调,但在我看来,它们更直观。
是的,我认为观察者模型会更好。我在某个地方读到,用java实现这一点有点困难,因为它运行在一个虚拟机上,要获得文件的侦听器,需要直接与os对话。我不确定的细节或有效性这虽然。

ut6juiuv

ut6juiuv2#

您不必使用轮询,您可以使用watchservice.take(),它在发生更改时立即返回。是的,它需要一个线程,但是单个线程可以用于监视多个对象。因此,很容易实现一个拥有监视线程并允许为每个对象注册回调的singleton。
至于第三方库,请看guava eventbus。我没有试过,也不确定是否适合你的需要。

tvz2xvvm

tvz2xvvm3#

我以亚历克赛的回答为基础,但我认为他还不够清楚。。。请看下面的示例代码:

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; 也是至关重要的;这是我在写关于亚历克赛答案的评论时忘记的。我的假设是 take() 由调用 register() ,因此在我的用户代码中不应返回任何键,因为register()已经使用了它。由于这个错误的假设,我没有意识到到底发生了什么。

相关问题