一部のシナリオでは、次のステップに進む前に、スレッドの実行が完了するまで待つ必要があります。たとえば、一部のプログラムでは、実行を開始する前に一部のリソースを初期化する必要があります。この時点で、初期化タスクを実行するためのスレッドを開始し、スレッド タスクが完了するまで待ってから他の部分を実行できます。
この目的のために、Thread クラスは join() メソッドを提供します。スレッド オブジェクトを使用してこのメソッドを呼び出すと、呼び出したスレッド オブジェクトは、呼び出されたオブジェクトの実行が完了するまで遅延してから実行を開始します。
このセクションでは、サンプル プログラムは、他のタスクを実行する前に初期化メソッドが完了するのを待つ方法を示します。
それを知っています
以下の手順でサンプルプログラムを完成させます。
1. DataSourcesLoader という名前のクラスを作成し、Runnable インターフェイスを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリック クラス DataSourcesLoader は Runnable {を実装します
2. run() メソッドを実装し、実行の開始を示すメッセージをコンソールに出力し、4 秒間スリープしてから、スレッドの実行の終了を示すメッセージをコンソールに出力します。コードは次のとおりです。
次のようにコードをコピーします。
@オーバーライド
public void run() {
System.out.printf("データ ソースの読み込みを開始しています: %s/n",
新しい日付());
試す {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("データ ソースの読み込みが完了しました: %s/n",
新しい日付());
}
3. NetworkConnectionsLoader という名前のクラスを作成し、Runnable インターフェイスを実装します。 run() メソッドを実装します。このメソッドのコードは、6 秒間スリープすることを除いて、DataSourcesLoader クラスの run() メソッドと同じです。
4. 例のメインクラスを実装し、main() メソッドを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリッククラス Main {
public static void main(String[] args) {
5. DataSourcesLoader オブジェクトと Thread オブジェクトを作成して、その実行を開始します。コードは次のとおりです。
次のようにコードをコピーします。
DataSourcesLoader dsLoader = new DataSourcesLoader();
スレッド thread1 = new Thread(dsLoader, "DataSourcesLoader");
6. NetworkConnectionsLoader オブジェクトと Thread オブジェクトを作成して、その実行を開始します。コードは次のとおりです。
次のようにコードをコピーします。
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
スレッド thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
7. 2 つの Thread オブジェクトの start() メソッドを呼び出します。コードは次のとおりです。
次のようにコードをコピーします。
thread1.start();
thread2.start();
8. join() メソッドを呼び出して、2 つのスレッドがタスクを完了するのを待ちます。このメソッドは InterruptedException をスローするため、この例外をキャッチします。コードは次のとおりです。
次のようにコードをコピーします。
試す {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
9. プログラムの実行の終了を示す文をコンソールに出力します。コードは次のとおりです。
次のようにコードをコピーします。
System.out.printf("メイン: 構成がロードされました: %s/n",
新しい日付());
10. プログラムを実行し、実行効果を確認します。
理由を知っています
このサンプル プログラムを実行すると、2 つのスレッドが実行を開始していることがわかります。まず、DataSourcesLoader が実行を完了し、次に NetworkConnectionsLoader が実行を完了します。この時点で、メインスレッドは実行を継続し、終了メッセージをコンソールに出力します。
終わりのない
Java には、他に 2 つのオーバーロードされた join() メソッドが用意されています。
次のようにコードをコピーします。
参加(長いミリ秒)
join(長いミリ秒、長いナノ)
最初のメソッドは、呼び出されたタスクが完了するまで待機しませんが、実行を開始する前にパラメータで指定された時間待機します。たとえば、thread1 スレッドが次のいずれかに出会ったときに、このメソッド thread1.join(1000) が呼び出されます。次の条件は引き続き実行されます。
1.thread2 が実行を完了します。
2.1000ミリ秒後;
これら 2 つの条件のいずれかが true の場合、join() メソッドは元のタスクに戻り、実行を継続します。
2 番目の方法は、追加のナノ秒時間パラメータがあることを除いて、最初の方法と非常に似ています。
ドクトリンを使用する
この記事は「Java 7 Concurrency Cookbook」(D Gua Ge が「Java7 Concurrency Example Collection」として盗用しました) を翻訳したものであり、学習教材としてのみ使用されます。許可なく商業目的で使用することはできません。
小さな成功
このセクションで使用されるサンプル コードの完全版。
DataSourcesLoader クラスの完全なコードは次のとおりです。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe6;
java.util.Dateをインポートします。
java.util.concurrent.TimeUnitをインポートします。
/**
* 日付: 2013-09-19
* 時間: 09:15
*/
パブリック クラス DataSourcesLoader は Runnable {を実装します
@オーバーライド
public void run() {
System.out.printf("データ ソースの読み込みを開始しています: %s/n",
新しい日付());
試す {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("データ ソースの読み込みが完了しました: %s/n",
新しい日付());
}
}
NetworkConnectionsLoader クラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe6;
java.util.Dateをインポートします。
java.util.concurrent.TimeUnitをインポートします。
/**
* 日付: 2013-09-19
* 時間: 09:21
*/
パブリック クラス NetworkConnectionsLoader は Runnable {を実装します
@オーバーライド
public void run() {
System.out.printf("データ ソースの読み込みを開始しています: %s/n",
新しい日付());
試す {
TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("データ ソースの読み込みが完了しました: %s/n",
新しい日付());
}
}
Mainクラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe6;
java.util.Dateをインポートします。
/**
* 日付: 2013-09-19
* 時間: 09:25
*/
パブリッククラス Main {
public static void main(String[] args) {
DataSourcesLoader dsLoader = new DataSourcesLoader();
スレッド thread1 = new Thread(dsLoader, "DataSourcesLoader");
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
スレッド thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
thread1.start();
thread2.start();
試す {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("メイン: 構成がロードされました: %s/n",
新しい日付());
}
}