Java WatchService APIとApache Commons IO Monitor Libraryの違い
1. 概要
JavaWatchServiceAPIがJava7でリリースされるずっと前に、Apache Commons IO Monitoringライブラリは、ファイルシステムの場所またはディレクトリの変更を監視するという同じユースケースにすでに取り組んでいました。
この記事では、2つのAPIの違いを探ります。
2. Mavenの依存関係
Apache Commons IOを使用するには、次の依存関係をpomに追加する必要があります。
commons-io
commons-io
2.5
そしてもちろん、監視サービスはJDKの一部であるため、外部の依存関係は必要ありません。
3. 機能比較
3.1. イベント駆動型処理
WatchService APIは、オペレーティングシステムによってトリガーされるファイルシステム変更イベントによって駆動されます。 このアプローチにより、アプリケーションが変更のためにファイルシステムを繰り返しポーリングすることがなくなります。
一方、Apache Commons IO Monitorライブラリは、FileクラスのlistFiles()メソッドを呼び出すことにより、構成可能なスリープ間隔でファイルシステムの場所をポーリングします。 このアプローチは、特に変更が発生しない場合、CPUサイクルを無駄にします。
3.2. コールバック方式
WatchServiceAPIはコールバックメソッドを提供しません。 代わりに、新しい変更イベントを処理できるかどうかを確認するために、2種類のポーリングメソッドを提供します。
-
poll()(タイムアウトパラメーター付き)やtake()などのブロックメソッド
-
poll()のようなノンブロッキングメソッド(タイムアウトパラメーターなし)
ブロッキングメソッドを使用すると、アプリケーションスレッドは、新しい変更イベントが利用可能になったときにのみ処理を開始します。 したがって、新しいイベントをポーリングし続ける必要はありません。
これらのメソッドの詳細と使用法については、記事hereを参照してください。
対照的に、Apache Commons IOライブラリは、ファイルシステムの場所またはディレクトリの変更が検出されたときに呼び出されるFileAlterationListenerインターフェイス上のコールバックメソッドを提供します。
FileAlterationObserver observer = new FileAlterationObserver("pathToDir");
FileAlterationMonitor monitor = new FileAlterationMonitor(POLL_INTERVAL);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
@Override
public void onFileCreate(File file) {
// code for processing creation event
}
@Override
public void onFileDelete(File file) {
// code for processing deletion event
}
@Override
public void onFileChange(File file) {
// code for processing change event
}
};
observer.addListener(listener);
monitor.addObserver(observer);
monitor.start();
3.3. イベントオーバーフロー
WatchService APIは、オペレーティングシステムのイベントによって駆動されます。 したがって、アプリケーションがイベントを十分に迅速に処理できない場合、イベントを保持するオペレーティングシステムのバッファがオーバーフローする可能性があります。 このシナリオでは、イベントStandardWatchEventKinds.OVERFLOWがトリガーされ、アプリケーションがイベントを読み取る前に、一部のイベントが失われたか破棄されたことを示します。
これには、アプリケーションでOVERFLOWイベントを適切に処理して、OVERFLOWイベントをトリガーする可能性のある突然の変更イベントのバーストをアプリケーションが確実に処理できるようにする必要があります。
一方、Commons IOライブラリはオペレーティングシステムイベントに基づいていないため、オーバーフローの問題はありません。
すべてのポーリングで、オブザーバーはディレクトリ内のファイルのリストを取得し、前のポーリングで取得したリストと比較します。
-
前回のポーリングで新しいファイル名が見つかった場合、リスナーでonFileCreate()が呼び出されます
-
前回のポーリングで見つかったファイル名が前回のポーリングで取得したファイルリストにない場合、リスナーでonFileDelete()が呼び出されます
-
一致するものが見つかった場合、ファイルの最終変更日、長さなどの属性の変更がチェックされます。 変更が検出されると、リスナーでonFileChange()が呼び出されます
4. 結論
この記事では、2つのAPIの主な違いを強調することに成功しました。
そして、いつものように、この記事で使用されている例の完全なソースコードはthe Github projectで入手できます。