Google Guava EventBus和Java 7 WatchService用于事件编程

这篇文章将介绍如何使用Guava EventBus将更改发布到Java 7 WatchService检测到的目录或子目录中。 Guava EventBus是向应用程序添加发布/订阅通信的好方法。 Java 7 java.nio.file软件包中新增的WatchService用于监视目录中的更改。 由于EventBus和WatchService已在以前的文章中介绍过,因此我们在这里不会深入介绍这些主题。 有关更多信息,鼓励读者查看EventBusWatchService帖子。 [注意:为清楚起见,帖子于2012年2月28日更新。]

为什么使用EventBus

将EventBus与WatchService一起使用的主要原因有两个。

  1. 我们不希望轮询事件,而是希望接收异步通知。
  2. 处理事件后,需要调用WatchKey.reset方法以使所有新更改都可以排队。 尽管WatchKey对象是线程安全的,但重要的是仅在所有线程完成处理事件之后才调用reset方法,这会导致一些协调麻烦。 使用单个线程处理事件,调用reset方法,然后通过EventBus发布更改,消除了此问题。

我们实现这一目标的计划很简单,将涉及以下步骤:

  1. 实例化WatchService的实例。
  2. 从给定的Path对象开始递归注册每个目录。
  3. 将事件从WatchService队列中移出,然后处理并发布这些事件。
  4. 启动一个单独的线程以使事件脱离队列并发布。

下面的代码示例是DirectoryEventWatcherImpl类中更相关的重点,它将完成所有这些工作。

在WatchService中注册目录

在添加或删除子目录时将生成事件,而监视目录的子目录进行的任何更改均不会。 我们将通过递归遍历所有子目录(通过Files.walkFileTree方法)并使用WatchService对象(在此示例中先前定义)注册每个子目录来对此进行补偿:

private void registerDirectories() throws IOException {
        Files.walkFileTree(startPath, new WatchServiceRegisteringVisitor());
}

private class WatchServiceRegisteringVisitor extends SimpleFileVisitor<Path>{
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
         dir.register(watchService,ENTRY_CREATE,ENTRY_DELETE,ENTRY_MODIFY);
         return FileVisitResult.CONTINUE;
    }
}

在第2行,Files.walkFileTree方法使用在第5行定义的WatchServiceRegisteringVisitor类向WatchService注册每个目录。 所注册的事件是文件/目录的创建,文件/目录的删除或文件的更新。

发布事件

下一步是创建一个FutureTask,它将执行检查队列和发布事件的工作。

private void createWatchTask() {
    watchTask = new FutureTask<>(new Callable<Integer>() {
       private int totalEventCount;
       @Override
       public Integer call() throws Exception {
           while (keepWatching) {
               WatchKey watchKey = watchService.poll(10, TimeUnit.SECONDS);
               if (watchKey != null) {
                  List<WatchEvent<?>> events = watchKey.pollEvents();
                  Path watched = (Path) watchKey.watchable();
                  PathEvents pathEvents = new PathEvents(watchKey.isValid(), watched);
                  for (WatchEvent event : events) {
                        pathEvents.add(new PathEvent((Path) event.context(), event.kind()));
                        totalEventCount++;
                  }
                  watchKey.reset();
                  eventBus.post(pathEvents);
                }
          }
           return totalEventCount;
        }
      });
    }

private void startWatching() {
  new Thread(watchTask).start();
}

在第7行,我们每10秒检查一次WatchService是否有排队事件。 当返回有效的WatchKey时,第一步是检索事件(第9行),然后获取发生事件的目录(第10行)。 在第11行,将创建一个PathEvents对象,该对象将一个布尔值和受监视的目录用作构造函数参数。 第12至15行使用目标Path和事件类型作为创建PathEvent对象的参数遍历第9行检索到的事件。 在第16行调用WatchKey.reset方法,将WatchKey状态设置回ready,使其有资格接收新事件并将其放回到队列中。 最后,在第17行,EventBus将PathEvents对象发布给所有订阅者。 重要的是在这里注意PathEvents和PathEvent类是不可变的。 从Callable返回的totalEventCount永远不会在API中公开,而是用于测试目的。 第25行的startWatching方法启动线程以运行上面定义的监视/发布任务。

结论

通过将WatchService与Guava EventBus配对,我们可以在单个线程中管理WatchKey并处理事件,并以异步方式通知任意数量的订阅者该事件。 希望读者发现此示例有用。 一如既往地欢迎提出意见和建议。

资源资源

参考: 事件编程示例:来自JCG合作伙伴 Bill Bejeck的Google Guava EventBus和Java 7 WatchService,来自“ 随机思考编码”博客。

翻译自: https://www.javacodegeeks.com/2012/12/google-guava-eventbus-and-java-7-watchservice-for-event-programming.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 1.介绍............................................................................................................................................................3 2.基本概念....................................................................................................................................................3 3.报文传输....................................................................................................................................................6 3.1 帧类型..................................................................................................................................................6 3.1.1 数据帧...........................................................................................................................................6 3.1.2 远程帧...........................................................................................................................................9 3.1.3 错误帧.........................................................................................................................................10 3.1.4 过载帧......................................................................................................................................... 11 3.1.5 帧间空间..................................................................................................................................... 11 3.2 发送器/接收器的定义.........................................................................................................................12 4.报文校验..................................................................................................................................................12 5.编码..........................................................................................................................................................13 6.错误处理..................................................................................................................................................13 6.1 错误检测............................................................................................................................................13 6.2 错误标定............................................................................................................................................13 7.故障界定..................................................................................................................................................13 8.位定时要求..............................................................................................................................................15 9 增加CAN 振荡器容差...............................................................................................................................16 9.1 协议修改............................................................................................................................................17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值