リソースを大量に消費するコードを並行して実行したい場合は、AFAIKのsubmiting Callable
/ Runnable
toが最適です。ExecutorService
したがって、私のメソッド構造:
public class ServiceClass {
protected final ExecutorService executorService = Executors.newCachedThreadPool();
public Future<Result> getResult(Object params) {
if (params == null) {
return null; // In situations like this the method should fail
}
// Do other fast pre-processing stuff
return executorService.submit(new CallProcessResult(params));
}
private class CallProcessResult implements Callable<Result> {
private Object params;
public CallProcessResult(Object params) {
this.params = params;
}
@Override
public Result call() throws Exception {
// Compute result for given params
// Failure may happen here too!
return result;
}
}
}
public class Result {
...
}
上記のコードで、障害が発生する可能性のある2つのスポットをマークしました。エラー処理に使用できるオプションは、これら2つの場合ではまったく異なります。
タスクを送信する前に、無効なパラメータ、失敗する可能性のある高速前処理コードなどの問題が発生する可能性があります。
ここで失敗を示すいくつかの方法があります。
- 無効の場合は、すぐにnull
params
を返します。この場合、呼び出すたびにnullが返さgetResult
れるかどうかを確認する必要があります。getResult
- 上記の代わりにチェック済みの例外をスローします。
Future<Result>
要求に応じてnullを返すaをインスタンス化しますget()
。私はApacheCommonsでそれを行いConcurrentUtils.constantFuture(null)
ます。getResult
この場合、私は常にnull以外の値を返すことを期待しますFuture<Result>
。2番目のケースと一致しているので、このオプションの方が好きです。
タスクの実行中に、メモリ不足、破損したファイル、使用できないファイルなどの重大なエラーが発生する可能性があります。
- タスクの結果はオブジェクトであるため、私の場合のより良いオプションはnullを返すことだと思います。
- また、チェックされた例外をスローして処理することもできます
ThreadPoolExecutor.afterExecute
(NiranjanBhatによって提案されたように)。JavaExecutorServiceタスクからの例外の処理を参照してください。
どちらがより良い習慣ですか(どちらの場合も)?
おそらく、これを行う別の方法や、使用する必要のあるデザインパターンがありますか?