前のセクション「スレッドの中断」では、実行中のスレッドを中断する方法と、スレッドを中断するためにスレッドに対して何をする必要があるかを説明しました。一般に、前のセクションで紹介した割り込みメカニズムを使用できます。ただし、スレッドが複数のメソッドに分散される複雑なアルゴリズムを実装している場合、またはメソッド呼び出しに再帰呼び出しがある場合は、スレッドの中断を制御するより良い方法を使用する必要があります。この目的のために、Java は InterruptedException を提供します。この例外は、割り込み要求が検出され、run() メソッドでキャッチされたときにスローされる可能性があります。
このセクションでは、スレッドを使用して指定されたディレクトリとそのサブディレクトリ内のファイルを検索し、InterruptedException を使用してスレッドの中断を制御する方法を示します。
それを知っています
以下の手順でサンプルプログラムを実装してください。
1. FileSearch という名前のクラスを作成し、Runnable インターフェイスを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリック クラス FileSearch は Runnable {を実装します
2. 2 つの変数 (1 つは検索対象のファイル名用、もう 1 つは検索対象のディレクトリの初期化用) を宣言し、クラスのコンストラクターを実装し、コンストラクターのパラメーターを使用して宣言した 2 つの変数を初期化します。コードは次のとおりです。
次のようにコードをコピーします。
プライベート文字列 initPath;
プライベート文字列ファイル名;
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = ファイル名;
}
3. run() メソッドを実装します。このメソッドは、fileName がパス名であるかどうかを確認します。その場合は、directoryProcess() メソッドを呼び出して処理します。 directoryProcess() メソッドは InterruptedException をスローするため、例外をキャッチする必要があります。コードは次のとおりです。
次のようにコードをコピーします。
@オーバーライド
public void run() {
ファイル file = 新しいファイル(initPath);
if (file.isDirectory()) {
試す {
ディレクトリプロセス(ファイル);
} catch (InterruptedException e) {
System.out.printf("%s: 検索は中断されました",
Thread.currentThread().getName());
}
}
}
元の記事では、メソッド名は processDirectory() と記載されています。しかし、以下の手順によれば、これは誤記となります。それで修正してください。
4. directoryProcess() メソッドを実装します。このメソッドは、指定されたディレクトリ内のすべてのファイルとサブディレクトリを読み取り、それらを処理します。このメソッドは、ディレクトリごとに再帰呼び出しを行い、パラメータで指定されたディレクトリを処理します。このメソッドはファイルごとに fileProcess() メソッドを呼び出します。すべてのディレクトリとファイルを処理した後、このメソッドはスレッドが中断されているかどうかを確認し、InterruptedException 例外をスローします。コードは次のとおりです。
次のようにコードをコピーします。
/**
* ディレクトリを処理する
*
* @param 処理対象のファイルディレクトリ
* @throws 中断例外
*/
private void directoryProcess(File file) throws InterruptedException {
ファイル[] リスト = file.listFiles();
if (null != リスト) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
ディレクトリプロセス(リスト[i]);
} それ以外 {
ファイルプロセス(リスト[i]);
}
}
}
if (Thread.interrupted()) {
新しい InterruptedException() をスローします。
}
}
5. fileProcess() メソッドを実装します。このメソッドは、処理中のファイルと検索するファイル名を比較します。ファイル名が等しい場合、メッセージがコンソールに出力されます。次に、スレッドは中断されたかどうかを確認し、中断された場合は InterruptedException をスローします。コードは次のとおりです。
次のようにコードをコピーします。
/**
* 処理されたファイル
*
* @param file 処理対象のファイル
* @throws 中断例外
*/
private void fileProcess(File file) throws InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s/n",
Thread.currentThread().getName()、
file.getAbsolutePath());
}
if (Thread.interrupted()) {
新しい InterruptedException() をスローします。
}
}
6. ここで、例のメインクラスを実装し、main() メソッドを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリッククラス Main {
public static void main(String[] args) {
7. FileSearch オブジェクトを作成して初期化し、タスクを実行するための Thread オブジェクトを作成します。次に、スレッドを開始します。コードは次のとおりです。
次のようにコードをコピーします。
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
スレッド thread = 新しいスレッド(fileSearch);
thread.start();
8. 10 秒待ってからスレッドを中断します。コードは次のとおりです。
次のようにコードをコピーします。
試す {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
9. 例を実行し、結果を確認します。
理由を知っています
以下はスレッドの実行結果です。出力から、FileSearch がスレッドの実行の中断を検出したときに、スレッドの実行がどのように終了されるかがわかります。
次のようにコードをコピーします。
スレッド 0: C:/autoexec.bat
Thread-0: 検索が中断されました
この例では、Java 例外を使用してスレッドの中断を制御します。この例を実行すると、プログラムは、指定されたディレクトリとそのサブディレクトリにターゲット ファイルが含まれているかどうかを確認します。たとえば、「/b/c/d」と入力すると、プログラムは directoryProcess() メソッドを 3 回再帰的に呼び出します。スレッドが割り込みを検出すると、再帰呼び出しが何度実行されても、InterruptedException がスローされ、プログラムは run() メソッドの実行を開始します。
終わりのない
InterruptedException 例外は通常、sleep() メソッドなどの Java 同時実行 API によってスローされます。
ドクトリンを使用する
この記事は「Java 7 Concurrency Cookbook」(D Gua Ge が「Java7 Concurrency Example Collection」として盗用しました) を翻訳したものであり、学習教材としてのみ使用されます。許可なく商業目的で使用することはできません。
小さな成功
FileSearch クラスの完全なコードは次のとおりです。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe4;
java.io.ファイルをインポートします。
/**
* 日付: 2013-09-18
* 時間: 18:21
*/
パブリック クラス FileSearch は Runnable {を実装します
プライベート文字列 initPath;
プライベート文字列ファイル名;
/**
* 初期化コンストラクター
*
* @param initPath 検索対象のディレクトリ
* @param fileName 検索するファイルの名前
*/
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = ファイル名;
}
@オーバーライド
public void run() {
ファイル file = 新しいファイル(initPath);
if (file.isDirectory()) {
試す {
ディレクトリプロセス(ファイル);
} catch (InterruptedException e) {
System.out.printf("%s: 検索は中断されました",
Thread.currentThread().getName());
}
}
}
/**
* ディレクトリを処理する
*
* @param 処理対象のファイルディレクトリ
* @throws 中断例外
*/
private void directoryProcess(File file) throws InterruptedException {
ファイル[] リスト = file.listFiles();
if (null != リスト) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
ディレクトリプロセス(リスト[i]);
} それ以外 {
ファイルプロセス(リスト[i]);
}
}
}
if (Thread.interrupted()) {
新しい InterruptedException() をスローします。
}
}
/**
* 処理されたファイル
*
* @param file 処理対象のファイル
* @throws 中断例外
*/
private void fileProcess(File file) throws InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s/n",
Thread.currentThread().getName()、
file.getAbsolutePath());
}
if (Thread.interrupted()) {
新しい InterruptedException() をスローします。
}
}
}
Mainクラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe4;
java.util.concurrent.TimeUnitをインポートします。
/**
* 日付: 2013-09-18
* 時間: 19:28
*/
パブリッククラス Main {
public static void main(String[] args) {
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
スレッド thread = 新しいスレッド(fileSearch);
thread.start();
試す {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}