public interface WatchService
extends Closeable
通过调用其register方法向监视服务注册Watchable对象,返回WatchKey以表示注册。 当检测到对象的事件时,将发信号通知密钥,如果当前未发出信号,则将其排队到监视服务,以便调用poll或take方法的消费者检索密钥并处理事件。 一旦处理了事件,消费者就会调用密钥的reset方法来重置密钥,该密钥允许密钥发出信号并随后用其他事件重新排队。
入门案例:
/**
* 文件监听
*/
public class WatchServiceDemo implements Runnable{
public static void main(String[] args) {
WatchServiceDemo watchServiceDemo = new WatchServiceDemo();
watchServiceDemo.run();
}
@Override
public void run() {
String path = "F:\\TestFile";
WatchService watchService;
try {
//WatchService 实例化
watchService = FileSystems.getDefault().newWatchService();
//遍历文件
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
//这里监听文件的创建、修改、删除
dir.register(watchService,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.OVERFLOW);
return FileVisitResult.CONTINUE;
}
});
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> watchEvent : key.pollEvents()) {
WatchEvent.Kind<?> kind = watchEvent.kind();
System.out.println("kind=="+kind);
if (kind.equals(StandardWatchEventKinds.OVERFLOW)){
System.out.println("file overflow...");
}
if (kind.equals(StandardWatchEventKinds.ENTRY_DELETE)){
System.out.println("file delete...");
}
if (kind.equals(StandardWatchEventKinds.ENTRY_MODIFY)){
System.out.println("file modify...");
}
if (kind.equals(StandardWatchEventKinds.ENTRY_CREATE)){
System.out.println("file create...");
}
WatchEvent<Path> watchEventPath= (WatchEvent<Path>)watchEvent;
//获取文件目录
Path filePath = (Path) key.watchable();
//获取文件名
Path fileName = watchEventPath.context();
System.out.println("filePath=="+filePath+" fileName=="+fileName);
}
boolean reset = key.reset();
System.out.println("reset==="+reset);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
WatchService实例化
WatchService watchService = FileSystems.getDefault().newWatchService();
将Path注册到WatchService中
dir.register(watchService,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.OVERFLOW);
- StandardWatchEventKinds.OVERFLOW:事件丢失或失去
- StandardWatchEventKinds.ENTRY_CREATE:目录内实体创建或本目录重命名
- StandardWatchEventKinds.ENTRY_MODIFY:目录内实体修改
- StandardWatchEventKinds.ENTRY_DELETE:目录内实体删除或重命名
WatchKey:该文件节点所绑定的监控信息池,当文件发生变化时所有的变化都会被导入监控池。监控池是静态的,只有当你主动去获取新的监控池时才会有更新的内容加入监控池。这就造成了系统接收到监控信息事件可能稍长的问题。
//获取下一个变化信息的监控池,如果没有变化就一直等待
WatchKey key = watchService.take();
//利用key.pollEvents()方法返回一系列的事件列表 WatchEvent<?> watchEvent
for (WatchEvent<?> watchEvent : key.pollEvents()) {
//得到 监听的事件类型
WatchEvent.Kind<?> kind = watchEvent.kind();
System.out.println("kind=="+kind);
if (kind.equals(StandardWatchEventKinds.OVERFLOW)){
System.out.println("file overflow...");
}
}
WatchEvent<Path> watchEventPath= (WatchEvent<Path>)watchEvent;
//获取文件目录
Path filePath = (Path) key.watchable();
//获取文件名
Path fileName = watchEventPath.context();
每次的到新的事件后,需要重置监听池
key.reset();
key.reset() 方法
每次take()或者poll()操作都会导致线程监控阻塞,每次操作文件可能需要长时间,如果监听目录下有其他事件发生,将会导致事件丢失。重置操作表示重启该线程,后续的事件都会被读到。
key.cancel()方法:关闭监听池服务