失敗時と成功時のシャットダウン
タスクの結果を調整します。
「失敗時と成功時のシャットダウン」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
よく使う2つのパターン
並行処理で処理を分散する場合、ほとんどは次の2つの形に分類できます。
- すべて成功する必要がある:いずれかが失敗したら、残りを中止します。
ShutdownOnFailureを使用します。 - 最初の成功を採用する:1つが成功したら、すぐに残りをキャンセルします。
ShutdownOnSuccessを使用します。
JDKには、この両方が標準で用意されています。
ShutdownOnFailureの考え方
ShutdownOnFailureは、すべてのタスクが成功する必要がある場合に使用します。たとえば、ユーザープロフィールと注文情報をまとめて取得する場合です。
いずれかのサブタスクが例外をスローすると、スコープが残りをキャンセルするため、処理を無駄にせずに済みます。
ShutdownOnFailureの例
join()の後にthrowIfFailed()を呼び出すと、失敗があれば最初の失敗をExecutionExceptionでラップして再スローします。
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var a = scope.fork(() -> fetch("profile"));
var b = scope.fork(() -> fetch("orders"));
scope.join();
scope.throwIfFailed();
System.out.println(a.get() + " + " + b.get());
}
}
static String fetch(String what) {
return what + "-ok";
}
}throwIfFailedの動作
throwIfFailed()はサブタスクを調べます。すべて成功していれば何もしません。いずれかが失敗していれば、元の例外をラップしてスローします。
関数を渡して、原因を独自の例外型に変換することもできます。
ShutdownOnSuccessの考え方
ShutdownOnSuccessは、冗長化や競争処理に使用します。複数のミラーに問い合わせ、最初に応答したものを採用する場合などです。
いずれかのサブタスクが成功した瞬間に、スコープが残りをキャンセルし、成功した結果を保存します。
ShutdownOnSuccessの例
result()で成功した値を取得します。どのサブタスクも成功しなかった場合は、これを呼び出すと例外がスローされます。
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
scope.fork(() -> queryMirror("eu"));
scope.fork(() -> queryMirror("us"));
scope.join();
System.out.println("Fastest answer: " + scope.result());
}
}
static String queryMirror(String region) {
return region + "-data";
}
}resultとgetの違い
違いに注意してください。
ShutdownOnFailure:各サブタスク固有のget()で読み取りますShutdownOnSuccess:スコープのresult()で、成功した1つの結果を読み取ります
キャンセルは協調的に行われる
スコープがシャットダウンすると、残りのサブタスクのスレッドに割り込みを送ります。適切に設計されたタスクは割り込みを確認し、速やかに停止します。
標準ライブラリのブロッキング呼び出しは、通常、割り込みに自動的に応答します。
タイムアウト付きのjoin
どちらのポリシーも期限をサポートしています。joinUntil(Instant)を呼び出すと、指定した時点までだけ待機し、その後TimeoutExceptionをスローしてスコープをシャットダウンします。
ポリシーの選択
次の1つの質問を自分に問いかけてください。すべての結果が必要ですか、それとも最初の1つだけでよいですか。
- すべての結果が必要で、エラー時にはすぐに失敗させる:
ShutdownOnFailure - いずれか1つの結果が必要で、最も速いものを採用する:
ShutdownOnSuccess
それ以外の場合は、StructuredTaskScopeをサブクラス化します。
カスタムポリシー
StructuredTaskScopeを拡張し、handleComplete(Subtask)をオーバーライドして、独自のルールを実装できます。たとえば、最初に成功したN件を収集したり、失敗数が一定数に達した時点でシャットダウンしたりできます。
理解度チェック
状況に合うポリシーを選びましょう。
まとめ
組み込みの2つのシャットダウンポリシーについて学びました。
- すべて成功する必要がある場合は、
ShutdownOnFailure、throwIfFailed、サブタスクごとのgetを使用します - 最初の成功を採用する場合は、
ShutdownOnSuccessとresultを使用します - シャットダウンでは、残りのサブタスクに協調的に割り込みを送ります
joinUntilで期限を追加でき、サブクラス化で独自のルールを追加できます
次は、エラー処理とキャンセルについて詳しく学びます。
よくある質問
「失敗時と成功時のシャットダウン」レッスンは無料ですか?
はい。「失敗時と成功時のシャットダウン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「失敗時と成功時のシャットダウン」で何を学びますか?
タスクの結果を調整します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「失敗時と成功時のシャットダウン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 構造化並行性モデル
- StructuredTaskScope
- 失敗時と成功時のシャットダウン
- エラー処理とキャンセル