并发编程 - 利用Event Bus模式实现目录文件变化捕捉

news2024/11/16 16:02:10

文章目录

  • Pre
  • 需求
  • Code
    • DirectoryTargetMonitor
    • FileChangeEvent
    • FileChangeListener
    • 测试

在这里插入图片描述

Pre

并发编程 - Event Bus 设计模式


需求

JDK自1.7版本后提供了WatchService类,该类可以基于事件通知的方式监控文件或者目录的任何变化,文件的改变相当于每一个事件(Event)的发生,针对不同的时间执行不同的动作,我们将结合NIO2.0中提供的WatchService和上一篇博文实现的Event Bus实现文件目录的监控的功能。


Code

在这里插入图片描述

DirectoryTargetMonitor

package com.artisan.dirmonitor;

import com.artisan.busevent.impl.EventBus;
import lombok.extern.slf4j.Slf4j;

import java.nio.file.*;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
@Slf4j
public class DirectoryTargetMonitor {

    private WatchService watchService;

    private final EventBus eventBus;

    private final Path path;

    private volatile boolean start = false;

    public DirectoryTargetMonitor(final EventBus eventBus,
                                  final String targetPath) {
        this(eventBus, targetPath, "");
    }

    /**
     * 构造Monitor的时候需要传入EventBus以及需要监控的目录
     *
     * @param eventBus
     * @param targetPath
     * @param morePaths
     */
    public DirectoryTargetMonitor(final EventBus eventBus,
                                  final String targetPath, final String... morePaths) {
        this.eventBus = eventBus;
        this.path = Paths.get(targetPath, morePaths);
    }

    public void startMonitor() throws Exception {
        this.watchService = FileSystems.getDefault().newWatchService();
        //为路径注册感兴趣的事件
        this.path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_CREATE);
        log.info("The directory {} is monitoring... \n", path);
        this.start = true;
        while (start) {
            WatchKey watchKey = null;
            try {
                //当有事件发生时会返回对应的WatchKey
                watchKey = watchService.take();
                watchKey.pollEvents().forEach(event ->
                {
                    WatchEvent.Kind<?> kind = event.kind();
                    log.info(kind.name());
                    Path path = (Path) event.context();
                    Path child = DirectoryTargetMonitor.this.path.resolve(path);
                    //提交FileChangeEvent到EventBus
                    eventBus.post(new FileChangeEvent(child, kind));
                });
            } catch (Exception e) {
                this.start = false;
            } finally {
                if (watchKey != null) {
                    watchKey.reset();
                }
            }
        }
    }

    public void stopMonitor() throws Exception {
        System.out.printf("The directory [%s] monitor will be stop...\n", path);
        Thread.currentThread().interrupt();
        this.start = false;
        this.watchService.close();
        System.out.printf("The directory [%s] monitor will be stop done.\n", path);
    }
}
    

在创建WatchService之后将文件的修改、删除、创建等注册给了WatchService,在指定目录下发生诸如此类的事件之后便会收到通知,将事件类型和发生变化的文件Path封装成FileChangeEvent提交给Event Bus。


FileChangeEvent

package com.artisan.dirmonitor;

import java.nio.file.Path;
import java.nio.file.WatchEvent;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 * @desc : FileChangeEvent比较简单,就是对WatchEvent.Kind和Path的包装,一旦目录发生任何改变,都会提交FileChangeEvent事件
 */
public class FileChangeEvent {
    private final Path path;
    private final WatchEvent.Kind<?> kind;

    public FileChangeEvent(Path path, WatchEvent.Kind<?> kind) {
        this.path = path;
        this.kind = kind;
    }

    public Path getPath() {
        return path;
    }

    public WatchEvent.Kind<?> getKind() {
        return kind;
    }
}
    

FileChangeListener

package com.artisan.dirmonitor;

import com.artisan.busevent.annotations.Subscribe;
import lombok.extern.slf4j.Slf4j;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 * @desc: 写一个接受文件目录变化的Subscriber,也就是当目录发生变化时用来接受事件的方法
 */
@Slf4j
public class FileChangeListener {


    @Subscribe
    public void onChange(FileChangeEvent event) {
        log.info("{}-{}\n", event.getPath(), event.getKind());
    }
}
    

onChange方法由@Subscribe标记,但没有指定topic,当有事件发送到了默认的topic上之后,该方法将被调用执行,接下来我们将FileChangeListener的实例注册给Event Bus并且启动Monitor程序


测试

package com.artisan.dirchange;

import com.artisan.busevent.impl.AsyncEventBus;
import com.artisan.busevent.impl.EventBus;
import com.artisan.dirmonitor.DirectoryTargetMonitor;
import com.artisan.dirmonitor.FileChangeListener;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class FileChangeTest {

    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(
                Runtime.getRuntime().availableProcessors() * 2);
        final EventBus eventBus = new AsyncEventBus(executor);
        //注册
        eventBus.register(new FileChangeListener());
        DirectoryTargetMonitor monitor = new DirectoryTargetMonitor(eventBus, "D:\\test");
        monitor.startMonitor();
    }
}

在子目录下不断地创建、删除、修改文件,这些事件都将被收集并且提交给EventBus
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/734782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java继承和多态

文章目录 继承继承概念继承的语法 super关键字super和this继承方式多态多态的概念多态实现条件 重写重写和重载的区别 继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;事物之间可能会…

Linux 内核级通用内存池 —— kmalloc 体系

目录 kmalloc 内存池中都有哪些尺寸的内存块 kmalloc 内存池如何选取合适尺寸的内存块 kmalloc 内存池的整体架构 KMALLOC_RECLAIM 表示需要分配可以被回收的内存&#xff0c;RECLAIM 类型的内存页&#xff0c;不能移动&#xff0c;但是可以直接回收&#xff0c;比如文件缓存页…

【Linux】第一个Linux小程序——进度条

今天为大家带来一篇关于在Linux上编写的进度条小程序的博客。 正文 我们在日常生活中使用电子产品时&#xff0c;经常会遇到加载的过程&#xff0c;这时候这些加载界面总是会附带有一些进度条&#xff0c;这些进度条是加载进度的可视化图形&#xff0c;这篇文章我们就在Linux系…

基于云原生网关的全链路灰度实践

作者&#xff1a; 倪海峰&#xff08;海迩&#xff09; 前言 随着企业规模的不断扩大&#xff0c;传统单体应用已很难进一步支持业务的发展&#xff0c;业务的迭代速度已经难以满足业务的增长&#xff0c;此时企业会对应用系统做微服务化的改造&#xff0c;降低业务的耦合度&…

keepalived脑裂

keepalived脑裂及解决方法&#xff1f; 一.keepalived的脑裂是如何产生的&#xff1f;二、HAProxy1.HAProxy概念2.HAProxy主要特性3.HAProxy负载均衡策略 4.LVS nginx HAProxy的区别5.编译部署HAProxy 一.keepalived的脑裂是如何产生的&#xff1f; 脑裂&#xff1a;指在一个高…

Elasticsearch【优化、案例】(八)-全面详解(学习总结---从入门到深化)

目录 Elasticsearch集群_测试集群状态 Elasticsearch集群_故障应对&水平扩容 Elasticsearch优化_磁盘选择 Elasticsearch优化_分片策略 Elasticsearch优化_内存设置 Elasticsearch案例_需求说明 Elasticsearch案例_ES自动补全 Elasticsearch案例_创建索引 Elastic…

多元分类预测 | Matlab 鲸鱼算法(WOA)优化xgboost的分类预测模型,多特征输入模型,WOA-xgboost分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab 鲸鱼算法(WOA)优化xgboost的分类预测模型,多特征输入模型,WOA-xgboost分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可…

MySQL查询作业

一、单表查询练习 1、查询出部门编号为30的所有员工 2、所有销售员的姓名、编号和部门编号。 3、找出奖金高于工资的员工。 4、找出奖金高于工资60%的员工。 5、找出部门编号为10中所有经理&#xff0c;和部门编号为20中所有销售员的详细资料。 6、找出部门编号为10中…

【三】部署zabbix-proxy代理服务器和高可用,以及监控windows系统和java应用

zabbix代理服务器和高可用 1.部署zabbix代理服务器1.1 代理端zabbix-proxy配置1.2 客户端zabbix-agent配置1.3 zabbix-proxy总结 2. 部署Zabbix高可用集群2.1 主节点zabbix-server配置2.2 备节点zabbix-server配置2.3 客户端zabbix_agent配置2.4 Zabbix高可用集群总结 3.Zabbix…

JavaScript异步编程:(回调函数、Promise、async/await、Generator)

文章目录 前言1. 回调函数1.1. 回调函数的基本概念和使用方法1.2. 回调函数的优缺点和注意事项1.3. 回调地狱和如何避免 2. Promise2.1. Promise 的基本概念和使用方法2.2. Promise 的状态和状态转换2.3. Promise 的链式调用和错误处理2.4. Promise.all 和 Promise.race 的使用…

MySQL数据库中对表进行创建,插入数据并对数据进行选择

目录 1.根据此图进行建表并插入数据 2.对表进行以下操作 a:显示所有职工的基本信息 b:查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号 c:求出所有职工的人数 d:列出最高工和最低工资 e:列出职工的平均工资和总工资 f:创建一个只有职工号、姓名和参加工作的…

123.HTML5+CSS3完结_使用Netlify收取表单

Netlify也可以做表单接受&#xff1a; 我们启动一下 修改下表单 ● 接着在我们的网站输入并提交表单 ● 之后会有一个提示&#xff0c;提示我们提交成功 然后就能在Netlify接受到用户的表单 ● 当然这个表单只能接受100个&#xff0c;但是作为实验也够用了 到此&a…

文字磨练课程:提高编辑和校对效率的方法

提高编辑和校对效率&#xff0c;可以使你更有效地完成写作任务&#xff0c;提升文章质量。以下是一些方法&#xff0c;可以帮助你在编辑和校对过程中提高效率。 1.设定目标和计划 在开始编辑和校对前&#xff0c;设定明确的目标和计划。这可以帮助你集中注意力&#xff0c;提…

【SQL应知应会】表分区(一)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • MySQL版 一、分区表1.非分区表2.分区表2…

整齐有序!统一命名文件,高效管理数据轻松实现!

在数字化时代&#xff0c;我们每天都与大量文件打交道&#xff0c;文件名杂乱无章、难以辨识的情况是司空见惯的。这不仅浪费我们宝贵的时间&#xff0c;还可能导致信息混乱和数据丢失。但是&#xff0c;抛开这一切困扰吧&#xff01;现在&#xff0c;我们向您介绍一个简单却强…

C++—string类

本期我们来学习C的string&#xff0c;本期内容相当的多&#xff0c;且有一定难度&#xff0c;需要大家静下心来看 目录 1.标准库中的string 1.1string类的介绍 1.2 string类的常用接口 构造函数、析构函数、赋值、拷贝构造 npos push_back append operator[ ] size …

什么是ASPICE认证

ASPICE&#xff1a; “AutomotiveSoftware ProcessImprovement and CapacityDetermination”&#xff0c;即汽车软件过程改进及能力评定。它是一个过程模型&#xff0c;由过程和能力度两个维度构成&#xff0c;用于评价汽车行业软件设计开发的能力水平。 ASPICE的6个级别&…

基于simulink进行场景变化检测(附源码)

一、前言 此示例演示如何及时分割视频。此示例中的算法可用于检测视频流中的重大变化&#xff0c;例如广告开始和结束的时间。场景变换在广告和营销中被广泛应用。通过改变场景&#xff0c;可以吸引消费者的注意力&#xff0c;传达产品或服务的特点和优势。例如&#xff0c;将…

包揽七项葵花奖 参编多项标准 萤石领跑智能家居+物联网云平台行业

7月9日&#xff0c;2023第七届“葵花奖”智能家居评选颁奖盛典在广交会展馆举行&#xff0c;萤石网络一举斩获7项重磅奖项。同时&#xff0c;萤石作为参编单位&#xff0c;受邀参与了《智能门锁测评标准》发布仪式及《智能开关测评标准》启动会&#xff0c;再次彰显了其在智能家…

【一些随笔】浅析 Linux和Windows:系统介绍、操作差异与使用技巧解析

一些随笔 文章内容1️⃣ 那些在Linux上顺理成章&#xff0c;换到Windows上就可能令人费解的事2️⃣ Linux系统介绍及使用技巧3️⃣ Windows系统介绍及使用技巧 文章内容 Linux和Windows系统的操作差异&#xff1b;Linux系统介绍、系统监控和优化技巧、Shell脚本编程技巧、一些…