
如果本機事件通知機制不可用,則默認實現將使用輪詢。 結果,響應性,事件的順序和可用細節是特定于實現的。 (注意:有一篇有關使用Guava EventBus處理WatchService事件的文章 )
觀看目錄
Path接口實現了將WatchService對象和WatchEvent.Kind類型的varargs作為參數的register方法。 有4個事件需要注意:
- ENTRY_CREATE
- ENTRY_DELETE
- ENTRY_MODIFY
- 溢出
前三種是不言自明的,而OVERFLOW則表示事件可能丟失或丟棄。 通過調用FileSystem.newWatchService()創建WatchService。 觀看目錄是通過在WatchService中注冊Path對象來完成的:
import static java.nio.file.StandardWatchEventKinds.*;
Path path = Paths.get("/home");
WatchService watchService = FileSystems.getDefault().newWatchService();
WatchKey watchKey = path.register(watchService,ENTRY_CREATE,ENTRY_DELETE,ENTRY_MODIFY);
從示例中可以看到,register方法返回一個WatchKey對象。 WatchKey是表示在WatchService中注冊路徑的令牌。
WatchKey
作為注冊過程的結果,WatchKey處于“就緒”狀態,并被視為有效。 WatchKey保持有效,直到發生以下情況之一:
- WatchKey.cancel()被調用。
- 正在監視的目錄不再可用。
- WatchService對象已關閉。
檢查變更
當檢測到更改時,WatchKey狀態將設置為“已信號發送”,并將其放入隊列中進行處理。 使WatchKeys脫離隊列涉及調用WatchService.poll()或WatchService.take()。 這是一個基本示例:
private boolean notDone = true;
while(notDone){try{WatchKey watchKey = watchService.poll(60,TimeUnit.SECONDS);List<WatchEvent.Kind<?>> events = watchKey.pollEvents();for(WatchEvent event : events){...process the events}if(!watchKey.reset()){...handle situation no longer valid}}catch(InterruptedException e){Thread.currentThread().interrupt();}
在第5行上,我們調用pollEvents方法來檢索此WatchKey對象的所有事件。 在第9行,您會注意到對reset方法的調用。 reset方法將WatchKey狀態重新設置為“就緒”,并返回一個布爾值,指示WatchKey是否仍然有效。 如果有任何未決事件,則WatchKey將立即重新排隊,否則它將保持就緒狀態,直到檢測到新事件。 在已取消或處于就緒狀態的WatchKey上調用reset無效。 如果WatchKey在排隊時被取消,它將在隊列中擴大直到被取回。 如果目錄已刪除或不再可用,取消也會自動發生。
處理事件
現在我們已經檢測到一個事件,我們如何確定:
- 事件發生在哪個目錄? (假設注冊了多個目錄)
- 實際事件是什么? (假設收聽多個事件)
- 事件的目標是什么,即創建,刪除或更新了哪個Path對象?
跳到上一個示例的第6行,我們將從WatchKey和WatchEvent中解析所需的信息:
//WatchKey watchable returns the calling Path object of Path.registerPath watchedPath = (Path) watchKey.watchable();//returns the event typeStandardWatchEventKinds eventKind = event.kind();//returns the context of the eventPath target = (Path)event.context();
在第6行,我們看到了WatchEvent.context方法被調用。 如果事件是創建,刪除或更新,并且該事件相對于監視目錄,則context方法將返回Path對象。 重要的是要知道,當收到事件時,不能保證執行該操作的程序已經完成,因此可能需要一定程度的協調。
結論
WatchService是Java 7中新的java.nio.file包的一個非常有趣的功能。也就是說,WatchService需要牢記兩件事:
- WatchService不會為監視目錄的子目錄拾取事件。
- 我們仍然需要輪詢WatchService的事件,而不是接收異步通知。
為了解決上述問題,有一篇后續文章,使用Guava EventBus處理WatchService事件 。 感謝您的寶貴時間,在下一篇文章中見。
資源資源
- java.nio.file軟件包,其中包含此處討論的WatchService,WatchKey和WatchEvent對象。
- 演示WatchService的單元測試
參考: Java 7的新增功能: JCG合作伙伴提供的 WatchService ? 比爾·貝杰克(Bill Bejeck)在“ 編碼隨機思想”博客上。
翻譯自: https://www.javacodegeeks.com/2012/02/java-7-watchservice.html