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. node-pre-gyp install --fallback-to-build 错误

    [node-pre-gyp install --fallback-to-build 错误] npm install bcrypt时遇上错误 此时,安装node-gyp npm install -g n ...

  2. 使用ddns搭建免费服务器

    [使用ddns搭建免费服务器] 第一步 tplink路由器提供了ddns服务,它为用户免费提供一个子tpddns.cn下的子域名,映射到你的路由器上.当启用后,只在要能接入互联网的地方,都能过此域名, ...

  3. python网络编程之开启进程的方式

    标签(空格分隔): 开启进程的方式 multiprocessing模块介绍: python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在pyth ...

  4. python网络编程之C/S架构介绍

    标签(空格分隔): c/s架构介绍 什么是C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),后续我们可以试着写个c/s软件实现服务器软件与客户端软件基于网络通信: 计 ...

  5. idea 安装和破解

    https://blog.csdn.net/SmileLvCha/article/details/78936659

  6. python 内置函数(一),低阶内置函数功能汇总

    python  内置函数  68个 今日主要内容: 1.内置函数 一.内置函数 1.内置函数 详细细节内容地址(id):https://mubu.com/edit/odv-2Dkb6j

  7. Struts学习资料

    Strust组件—ActionServlet详解 http://ltc603.iteye.com/blog/68637

  8. LocalDateTime TypeMismatch

    @DateTimeFormat(pattern = "yyyy-MM-dd")@JsonFormat(pattern = "yyyy-MM-dd", timez ...

  9. .resources文件转为可视化.resx文件

    ResGen.exe启动闪退.--方法不对 参考:http://www.opdown.com/soft/101205.html 在cmd中启动ResGen.exe. 打开cmd:输入 C:\Windo ...

  10. .net 中使用oracle 的sql 语句

    string sqlString = "Select * From emp  Where EMPNO=7369“; 一定不要写成 string sqlString = "Selec ...