2.17.6 Future<V>オブジェクトによる非同期メソッドの実行状態および実行結果に対する操作
非同期メソッドの戻り値にFuture<V>を指定した場合,Future<V>オブジェクトのメソッドを使用して次の処理ができます。これらの処理は,戻り値がvoidの場合は実行できません。
-
非同期呼び出し処理のキャンセル
-
非同期呼び出し処理の実行結果の取得
-
非同期呼び出し処理の実行状態の確認
-
非同期呼び出し処理で例外が発生した場合の要因取得
- 〈この項の構成〉
(1) 非同期呼び出し処理のキャンセル
Future<V>オブジェクトのcancelメソッドを使用して,処理をキャンセルできます。
キャンセルに成功した場合は,メソッドの戻り値としてtrueが返却されます。キャンセルできなかった場合は,戻り値としてfalseが返却されます。
非同期呼び出しがキャンセルできなかった場合は,cancelメソッドのmayInterruptIfRunningパラメタの指定によって,処理が中断されるか,処理がそのまま実行されるかが決まります。
(2) 非同期呼び出し処理の実行結果の取得
Future<V>オブジェクトのgetメソッドを使用して,実行結果を取得できます。
処理が成功して処理結果が戻り値として取得できた場合,またはExecutionExceptionが発生した場合は,処理が完了しています。これ以降に同じFuture<V>オブジェクトを使用して実行結果を取得した場合,同じ結果を取得できます。
なお,アプリケーションサーバでは,Future<V>オブジェクトのメソッド呼び出しでタイムアウトが発生した場合,EJBコンテナによってEJBExceptionがクライアントに対してスローされます。
(3) 非同期呼び出し処理の実行状態の確認
非同期呼び出し処理の実行が完了したかどうか,キャンセルされたかどうかを確認できます。状態は,Future<V>オブジェクトの次のメソッドで確認できます。
-
isDoneメソッド
処理が正常に完了している場合,例外が発生している場合,およびキャンセルされた場合にtrueが返されます。
-
isCancelledメソッド
処理のキャンセルが成功している場合にtrue,キャンセルできなかった場合にfalseが返されます。
また,非同期メソッドの側で,クライアントからcancelメソッドが呼び出されたかどうかは,次のメソッドで確認できます。
-
wasCancelCalledメソッド
cancelメソッドによって非同期呼び出し処理の実行のキャンセルが呼び出された場合に,cancelメソッドのmayInterruptIfRunningパラメタにtrue(実行中の処理を停止する)が指定されていたときはtrue,false(実行中の処理を完了させる)が指定されたときはfalseが返されます。
(4) 非同期呼び出し処理で例外が発生した場合の要因取得
ビジネスインタフェースのメソッドでシステム例外が発生した場合,呼び出し元のクライアントには,javax.ejb.EJBExceptionなどの代わりに,java.rmi.RemoteExceptionが返されます。非同期呼び出し処理でシステム例外を受け取った場合,クライアントでは,非同期メソッドが実行されなかったと判断できます。この場合は,再度非同期メソッドの呼び出しを実行できます。
アプリケーション例外など,システム例外以外の例外が発生した場合,クライアントはEJBコンテナによって非同期処理が実行された上で,非同期処理の中で例外が発生したと判断できます。この場合は,例外オブジェクトを使用して,要因を取得できます。
非同期呼び出し時に例外が発生した場合に例外オブジェクトのgetCauseメソッドを呼び出して,原因を取得するコーディング例を次に示します。
// Bean Client Future future = asynSessionBean.performCalculation(); while (!future.isDone()) { Thread.currentThread().sleep(10000); future.cancel(true); break; } if (future.isCancelled() == false) { Integer answer = null; try{ answer = (Integer)future.get(); } catch(ExecutionException e){ System.out.println("caught exception: " +e.getCause()); } System.out.println("Answer=" + answer.toString()); } asynSessionBean.performAddition();