内容简介:嫌我啰嗦的话,直接看代码:在写个小东西需要监控文件改变状态的时候,用到了 NIO 东西很方便也好用。但是,在使用首先,使用原生的接口必须开启个线程,然后使用个持续循环去读取 WatchEvent (这也是大部分教程描述这样子做的):
嫌我啰嗦的话,直接看代码: https://github.com/mingcheng/rx-filewatcher.java
在写个小东西需要监控文件改变状态的时候,用到了 NIO 东西很方便也好用。但是,在使用 WatchService 的时候碰到了些问题。
首先,使用原生的接口必须开启个线程,然后使用个持续循环去读取 WatchEvent (这也是大部分教程描述这样子做的):
WatchKey key; while ((key = watchService.take()) != null) { for (WatchEvent<?> event : key.pollEvents()) { //process } key.reset(); }
这样子做有几个不好的地方:一是开了个匿名线程,如果后期代码也有类似的情况,线程就不好处理,而且很容易无法监控到这个线程的状态;第二就是破坏了代码原有的业务逻辑,读到这里如果阅读代码的小伙伴不熟悉 WatchService
就很难理解。
其次, WatchService
的注册是一次性的,也就是说无法监控到子目录以下的情况,必须随时监控是否创建了子目录然后再对应 register 子目录 watch(这样子一个简单的功能就会搞得非常的复杂)。
我考虑到使用 Rx 重写这块的代码, 然后翻阅 Github 的时候发现已经有人造了这个轮子 。代码量不大,但核心功能是我想要的,只是最新更新已经在三年前了。
集成了 Helmbold 这个哥们的库以后,又发现了几个问题:
1. 这个库是写在三年前的,还在用 Rx1 的库,和我目前的 Rx2 有部分的不兼容; 2. dispose 部分有问题,dispose 以后线程没有终止还在运行; 3. 获取到 WatchEvent 的 Context 只有文件名没有路径。
因为代码量本身就不是很多,同时考虑到这块还是需要以后自己维护, 因此 fork 了他的代码自己做了些改造 。
对比以上的原生代码,使用 Rx 封装的代码就会干净和直观很多:
PathObservables .subscribeOn(Schedulers.io()) .watchRecursive(Paths.get("some/directory/")) .subscribe(event -> System.out.println(event));
然后,基本上已经满足了我的需求。
顺便说下,WatchService 里面还有个坑,就是使用网络磁盘映射的时候,可能会造成 WatchEvent 会有丢失, 在这里有详细的讨论,这是目前 NIO 已知的 Bug 。如果你对文件状态监控要求实时性比较高,建议不要使用 WatchService 使用其他的方案。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 封装JDBC—非框架开发必备的封装类
- SpringBlade 2.3.2 发布,增加 OSS 封装及单元测试封装
- SpringBlade 2.3.2 发布,增加 OSS 封装及单元测试封装
- docker 封装 alinode
- 封装Apk签名工具
- axios封装笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。