日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Review - 使用Event Bus实现目录变化的监控

發布時間:2025/3/21 java 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Review - 使用Event Bus实现目录变化的监控 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • Pre
  • 需求
  • Event Bus案例實戰
  • 小結


Pre

Java Review - Java進程內部的消息中間件_Event Bus設計模式


需求

監控文件的實時變化 , 就這一句話???

分析一下其中一個有問題的思路:

程序首次啟動時獲取該文件的最后修改時間并且做文件的首次解析,然后每隔一段指定的時間檢查一次文件最后被修改的時間,如果與記錄的時間相等則等待下次的采集(Balking Pattern),否則進行新一輪的采集并且更新時間。

這。。。。有問題啊 , 比如在采集時間間隔內,文件發生了N次變化,只能獲取到最后一次,其根本原因是文件的變化不會通知到應用程序, 我只能傻傻的輪詢~

新思路:

JDK自1.7版本后提供了WatchService類,該類可以基于事件通知的方式監控文件或者目錄的任何變化,文件的改變相當于每一個事件(Event)的發生,針對不同的時間執行不同的動作,結合NIO2.0中提供的WatchService和Event Bus實現文件目錄的監控的功能。


Event Bus案例實戰

import com.artisan.bfzm.eventbus.EventBus;import java.nio.file.*;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/12/2 16:37* @mark: show me the code , change the world*/ 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);System.out.printf("The directory [%s] is monitoring... \n", path);this.start = true;while (start) {WatchKey watchKey = null;try {//當有事件發生時會返回對應的WatchKeywatchKey = watchService.take();watchKey.pollEvents().forEach(event ->{WatchEvent.Kind<?> kind = event.kind();Path path = (Path) event.context();Path child = DirectoryTargetMonitor.this.path.resolve(path);//提交FileChangeEvent到EventBuseventBus.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.

import java.nio.file.Path; import java.nio.file.WatchEvent;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/12/2 16:48* @mark: show me the code , change the world*/ 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;} }

FileChangeEvent是對WatchEvent.Kind和Path的包裝,一旦目錄發生任何改變,都會提交FileChangeEvent事件。

目錄監控的程序我們已經實現了,下面就來寫一個接受文件目錄變化的Subscriber,也就是當目錄發生變化時用來接受事件的方法

import com.artisan.bfzm.eventbus.Subscribe;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/12/2 17:06* @mark: show me the code , change the world*/ public class FileChangeListener {@Subscribepublic void onChange(FileChangeEvent event) {System.out.printf("%s-%s-%s\n", Thread.currentThread().getName(),event.getPath(), event.getKind());} }

onChange方法由@Subscribe標記,但沒有指定topic,當有事件發送到了默認的topic上之后,該方法將被調用執行,接下來我們將FileChangeListener的實例注冊給Event Bus并且啟動Monitor程序

import com.artisan.bfzm.eventbus.AsyncEventBus; import com.artisan.bfzm.eventbus.EventBus;import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/12/2 17:15* @mark: show me the code , change the world*/ public class FileDirTest {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, "C:\\Users\\artisan\\Desktop\\aaa");monitor.startMonitor();} }

小結

EventBus有點類似于GOF設計模式中的監聽者模式,但是EventBus提供的功能更加強大,使用起來也更加靈活,EventBus中的Subscriber不需要繼承任何類或者實現任何接口,在使用EventBus時只需要持有Bus的引用即可。

在EventBus的設計中有三個非常重要的角色(Bus、Registry和Dispatcher),Bus主要提供給外部使用的操作方法,Registry注冊表用來整理記錄所有注冊在EventBus上的Subscriber,Dispatcher主要負責對Subscriber消息進行推送(用反射的方式執行方法),但是考慮到程序的靈活性,Dispatcher方法中又提供了Executor的多態方式。

總結

以上是生活随笔為你收集整理的Java Review - 使用Event Bus实现目录变化的监控的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。