JDK 之 NIO 2 WatchService、WatchKey(监控文件变化)

JDK 规范目录(https://www.cnblogs.com/binarylei/p/10200503.html)

一、WatchService、WatchKey 使用

具体详见:https://blog.csdn.net/lirx_tech/article/details/51425364

public static void main(String[] args) throws Exception {
// 1. 获取文件系统监控器,启动一个后台线程轮询
WatchService watchService = FileSystems.getDefault().newWatchService(); // 2. 注册要监听的事件类型,文件增、删、改
Paths.get("C:\\Users\\len\\Desktop\\xdr").register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY); while (true) {
// 3. 获取准备好的事件,pool() 立即返回、take() 阻塞
WatchKey watchKey = watchService.poll(2, TimeUnit.SECONDS);
if (Objects.isNull(watchKey)) {
continue;
}
// 4. 处理准备好的事件
List<WatchEvent<?>> watchEvents = watchKey.pollEvents();
for (WatchEvent<?> event : watchEvents) {
if (event.kind().name().equals(StandardWatchEventKinds.ENTRY_CREATE.name())) {
System.out.println("create: " + event.context());
} else if (event.kind().name().equals(StandardWatchEventKinds.ENTRY_MODIFY.name())) {
System.out.println("modify: " + event.context());
} else if (event.kind().name().equals(StandardWatchEventKinds.ENTRY_DELETE.name())) {
System.out.println("delete: " + event.context());
}
}
// 5. 重启该线程,因为处理文件可能是一个耗时的过程,因此调用 pool() 时需要阻塞监控器线程
boolean valid = watchKey.reset();
if (!valid) {
break;
}
}
}

二、原理

  • AbstractWatchService 实现 WatchService 接口
  • WindowsWatchService 具体的实现,启动 Poller 线程
  • Poller 线程,轮询指定的目录

(1) AbstractWatchService

// 等待要处理的事件 signaled keys waiting to be dequeued
private final LinkedBlockingDeque<WatchKey> pendingKeys = new LinkedBlockingDeque<WatchKey>(); @Override
public final WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException {
checkOpen();
WatchKey key = pendingKeys.poll(timeout, unit);
checkKey(key);
return key;
}

可以看到调用 poll 的时候直接从队列中取 key,那就必然有一个线程往 pendingKeys 中塞数据。在 AbstractWatchService 中有一个 enqueueKey 方法往 pendingKeys 中塞数据。

final void enqueueKey(WatchKey key) {
pendingKeys.offer(key);
}

(2) WindowsWatchService

AbstractWatchService 有不同的实现,以 WindowsWatchService 为例。

WindowsWatchService(WindowsFileSystem fs) throws IOException {
// create I/O completion port
long port = 0L;
try {
port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0);
} catch (WindowsException x) {
throw new IOException(x.getMessage());
}
this.poller = new Poller(fs, this, port);
this.poller.start();
}

Poller 是 WindowsWatchService 的内部类,开启了一个线程监控目录。

(3) Poller

重点关注 Poller 中的 run 方法。

@Override
public void run() {
for (;;) {
CompletionStatus info;
try {
info = GetQueuedCompletionStatus(port);
} catch (WindowsException x) {
return;
} WindowsWatchKey key = ck2key.get((int)info.completionKey());
if (key == null) {
continue;
}
boolean criticalError = false;
if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
} else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
criticalError = true;
} else {
// 省略... (处理 error)
} // 一切正常则 criticalError = true,此时将这个 WatchKey 加入 pendingKeys 中
if (criticalError) {
implCancelKey(key);
key.signal();
}
}
}

参考:

  1. 《NIO.2:WatchService、WatchKey(监控文件变化)》:(https://blog.csdn.net/lirx_tech/article/details/51425364)

每天用心记录一点点。内容也许不重要,但习惯很重要!

JDK 之 NIO 2 WatchService、WatchKey(监控文件变化)的更多相关文章

  1. 利用WatchService监听文件变化

    在实现配置中心的多种方案中,有基于JDK7+的WatchService方法,其在单机应用中还是挺有实践的意义的. 代码如下: package com.longge.mytest; import jav ...

  2. Python监控文件变化:watchdog

    Python监控文件变化有两种库:pyinotify和watchdog.pyinotify依赖于Linux平台的inotify,后者则对不同平台的的事件都进行了封装.也就是说,watchdog跨平台. ...

  3. mac 监控文件变化并重启php

    自己撸一个框架,需要监控代码变化 安装fswatch brew install fswatch shell重启PHP脚本reload.sh #!/bin/sh do ps -ef | grep php ...

  4. linux 监控文件变化

    介绍 有时候我们常需要当文件变化的时候便触发某些脚本操作,比如说有文件更新了就同步文件到远程机器.在实现这个操作上,主要用到两个工具,一个是rsync,一个是inotifywait .inotifyw ...

  5. inotifywait命令如何监控文件变化?

    转载自:https://segmentfault.com/a/1190000038351925 文件监控可以配合rsync实现文件自动同步,例如监听某个目录,当文件变化时,使用rsync命令将变化的文 ...

  6. Gulp-前端进阶A-3---如何不刷新监控文件变化?

    npm install --save-dev gulp-connect npm install --save-dev gulp-livereload npm其他,前面已有 var gulp = req ...

  7. 使用apache common-io 监控文件变化--转

    package common.io; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.common ...

  8. 利用nodejs监控文件变化并使用sftp上传到服务器

    很久没写博客了,因为最近在用react+express做一个自己的工具型网站(其实就是夺宝岛抢拍器) 然后因为经常要改动,而且又要放到服务器上进行测试.总是要webpack,然后手动把文件上传上去,不 ...

  9. 使用apache common-io 监控文件变化

    package common.io; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.common ...

随机推荐

  1. 部署Java的运行环境

    1.先去官网下载最新的jdk 网址:http://www.oracle.com/technetwork/java/javase/downloads/ 2.用tar zxvf解压相应的文档到相应的路径 ...

  2. iptables禁止别人,允许自己

    这里举个例子,以ping为案例:禁止别人ping自己,但允许自己ping别人. [root@localhost ~]# iptables -A INPUT -p icmp --icmp-type 8 ...

  3. 1.5、CDH 搭建Hadoop在安装之前(定制安装解决方案)

    Cloudera托管两种类型的软件存储库,您可以使用它们来安装诸如Cloudera Manager或CDH-parcel存储库和软件包存储库之类的产品. 在大多数情况下,这些存储库是有效的解决方案,但 ...

  4. poj2912(带权并查集+枚举)

    题目链接:http://poj.org/problem?id=2912 题意:给n个人,m组关系,玩石头剪刀布的游戏,n个人中除一个人judge以外,其他人属于3个group(即石头.剪刀.布),他们 ...

  5. Tensorflow函数——tf.variable_scope()

    Tensorflow函数——tf.variable_scope()详解 https://blog.csdn.net/yuan0061/article/details/80576703 2018年06月 ...

  6. shape 图形

    主要属性: <?xml version="1.0"encoding="utf-8"?><shape > <corners /> ...

  7. HUABASE :基于列存储的关系型数据库系统

    摘要   HUABASE 是基于列存储的关系型数据库系统.列存储技术的特点是数据查询效率高,读磁盘少,存储空间少,是构建数据仓库的理想架构. HUABASE 实现了多种数据压缩机制.查询优化和稀疏索引 ...

  8. unittest 单元测试

    unittest 单元测试: 1,单元测试是指对软件中最小可测试单元进行检查和验证.对于单元测试中单元的含义,一般来讲,要根据实际情况去判定其具体含义. 2,unitest=TestCase + Te ...

  9. cocoapods 更新本地仓库 pod setup/update 无限远程中断

    升级 cocoapods 无限远程中断:网络不好 试了很多解决方法: 1.替换源,2.设置下载速度,3.清空本地master仓库,4.删了本地的pod库,5.半夜3-5点更新,6.按照失败提示的 (p ...

  10. 定时器修改button标题闪烁

    在做一个项目时,用到UIButton来设置接收短信验证码的倒计时,但是用NSTimer来设置标题会出现连续闪烁的问题. 经过测试发现了一下内容,如果只是单独的设置button的titleLabel的内 ...