欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

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

发布时间:2023/12/3 59 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Google Guava EventBus和Java 7 WatchService用于事件编程 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

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

为什么使用EventBus

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

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

  • 实例化WatchService的实例。
  • 从给定的Path对象开始递归注册每个目录。
  • 将事件从WatchService队列中移出,然后处理并发布这些事件。
  • 启动一个单独的线程以使事件脱离队列并发布。
  • 下面的代码示例是DirectoryEventWatcherImpl类中更相关的重点,它将完成所有这些工作。

    在WatchService中注册目录

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

    private void registerDirectories() throws IOException {Files.walkFileTree(startPath, new WatchServiceRegisteringVisitor()); }private class WatchServiceRegisteringVisitor extends SimpleFileVisitor<Path>{@Overridepublic 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;@Overridepublic 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并处理事件,并以异步方式通知任意数量的订阅者该事件。 希望读者发现此示例有用。 一如既往地欢迎提出意见和建议。

    资源资源

      • 这篇文章的源代码和单元测试
      • EventBus API
      • WatchService API
      • WatchService上的上一篇文章 。
      • EventBus上的上一篇文章

    参考: 事件编程示例:来自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

    总结

    以上是生活随笔为你收集整理的Google Guava EventBus和Java 7 WatchService用于事件编程的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。